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 ;
42 symbol *returnLabel ; /* function return label */
43 symbol *entryLabel ; /* function entry label */
44 /*-----------------------------------------------------------------*/
45 /* forward definition of some functions */
46 operand *geniCodeDivision (operand *,operand *);
47 operand *geniCodeAssign (operand *,operand *,int);
48 operand *geniCodeArray (operand *,operand *);
49 operand *geniCodeArray2Ptr (operand *);
50 operand *geniCodeRValue (operand *, bool );
51 operand *geniCodeDerefPtr (operand *);
53 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
54 /* forward definition of print functions */
55 PRINTFUNC(picGetValueAtAddr);
56 PRINTFUNC(picSetValueAtAddr);
58 PRINTFUNC(picGeneric);
59 PRINTFUNC(picGenericOne);
65 PRINTFUNC(picJumpTable);
67 PRINTFUNC(picReceive);
69 iCodeTable codeTable[] = {
70 { '!' , "not", picGenericOne , NULL },
71 { '~' , "~" , picGenericOne , NULL },
72 { RRC , "rrc", picGenericOne , NULL },
73 { RLC , "rlc", picGenericOne , NULL },
74 { GETHBIT ,"ghbit", picGenericOne , NULL },
75 { UNARYMINUS , "-" , picGenericOne , NULL },
76 { IPUSH , "push",picGenericOne , NULL },
77 { IPOP , "pop", picGenericOne , NULL },
78 { CALL , "call",picGenericOne , NULL },
79 { PCALL , "pcall",picGenericOne , NULL },
80 { FUNCTION , "proc", picGenericOne , NULL },
81 { ENDFUNCTION ,"eproc", picGenericOne , NULL },
82 { RETURN , "ret", picGenericOne , NULL },
83 { '+' , "+" , picGeneric , NULL },
84 { '-' , "-" , picGeneric , NULL },
85 { '*' , "*" , picGeneric , NULL },
86 { '/' , "/" , picGeneric , NULL },
87 { '%' , "%" , picGeneric , NULL },
88 { '>' , ">" , picGeneric , NULL },
89 { '<' , "<" , picGeneric , NULL },
90 { LE_OP , "<=" , picGeneric , NULL },
91 { GE_OP , ">=" , picGeneric , NULL },
92 { EQ_OP , "==" , picGeneric , NULL },
93 { NE_OP , "!=" , picGeneric , NULL },
94 { AND_OP , "&&" , picGeneric , NULL },
95 { OR_OP , "||" , picGeneric , NULL },
96 { '^' , "^" , picGeneric , NULL },
97 { '|' , "|" , picGeneric , NULL },
98 { BITWISEAND , "&" , picGeneric , NULL },
99 { LEFT_OP , "<<" , picGeneric , NULL },
100 { RIGHT_OP , ">>" , picGeneric , NULL },
101 { GET_VALUE_AT_ADDRESS, "@" , picGetValueAtAddr, NULL },
102 { ADDRESS_OF , "&" , picAddrOf , NULL },
103 { CAST , "<>" , picCast , NULL },
104 { '=' , ":=" , picAssign , NULL },
105 { LABEL , "" , picLabel , NULL },
106 { GOTO , "" , picGoto , NULL },
107 { JUMPTABLE ,"jtab" , picJumpTable , NULL },
108 { IFX , "if" , picIfx , NULL },
109 { INLINEASM , "" , picInline , NULL },
110 { RECEIVE , "recv", picReceive , NULL },
111 { SEND , "send", picGenericOne , NULL }
115 /*-----------------------------------------------------------------*/
116 /* operandName - returns the name of the operand */
117 /*-----------------------------------------------------------------*/
118 int printOperand (operand *op, FILE *file)
133 opetype = getSpec (operandType(op));
134 if (SPEC_NOUN(opetype) == V_FLOAT)
135 fprintf (file,"%g {", SPEC_CVAL(opetype).v_float);
137 fprintf (file,"0x%x {",(int) floatFromVal(op->operand.valOperand));
138 printTypeChain(operandType(op),file);
145 fprintf (file,"%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d}",/*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" ,*/
146 (OP_SYMBOL(op)->rname[0] ? OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name),
148 OP_LIVEFROM(op),OP_LIVETO(op),
149 OP_SYMBOL(op)->stack,
150 op->isaddr, OP_SYMBOL(op)->isreqv,OP_SYMBOL(op)->remat
153 fprintf(file,"{"); printTypeChain(operandType(op),file);
154 if (SPIL_LOC(op) && IS_ITEMP(op))
155 fprintf(file,"}{ sir@ %s",SPIL_LOC(op)->rname);
160 /* if assigned to registers */
161 if (OP_SYMBOL(op)->nRegs) {
162 if (OP_SYMBOL(op)->isspilt) {
163 if (!OP_SYMBOL(op)->remat)
164 if (OP_SYMBOL(op)->usl.spillLoc)
165 fprintf(file,"[%s]",(OP_SYMBOL(op)->usl.spillLoc->rname[0] ?
166 OP_SYMBOL(op)->usl.spillLoc->rname :
167 OP_SYMBOL(op)->usl.spillLoc->name));
169 fprintf(file,"[err]");
171 fprintf(file,"[remat]");
176 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
177 fprintf(file,"%s ", port->getRegName(OP_SYMBOL(op)->regs[i]));
182 fprintf(file,"%s",(OP_SYMBOL(op)->rname[0] ?
183 OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name));
184 /* if assigned to registers */
185 if (OP_SYMBOL(op)->nRegs && !OP_SYMBOL(op)->isspilt) {
188 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
189 fprintf(file,"%s ",(OP_SYMBOL(op)->regs[i] ?
190 OP_SYMBOL(op)->regs[i]->name :
199 printTypeChain(op->operand.typeOperand,file);
210 /*-----------------------------------------------------------------*/
211 /* print functions */
212 /*-----------------------------------------------------------------*/
213 PRINTFUNC(picGetValueAtAddr)
216 printOperand (IC_RESULT(ic),of);
219 printOperand (IC_LEFT(ic), of);
225 PRINTFUNC(picSetValueAtAddr)
229 printOperand(IC_LEFT(ic),of);
231 printOperand(IC_RIGHT(ic),of);
238 printOperand(IC_RESULT(ic),of);
239 if (IS_ITEMP(IC_LEFT(ic)))
243 printOperand(IC_LEFT(ic),of);
245 if (IS_ITEMP(IC_LEFT(ic)))
246 fprintf(of," offsetAdd ");
249 printOperand(IC_RIGHT(ic),of);
251 if (IS_ITEMP(IC_LEFT(ic)))
257 PRINTFUNC(picJumpTable)
262 fprintf(of,"%s\t",s);
263 printOperand(IC_JTCOND(ic),of);
265 for ( sym = setFirstItem(IC_JTLABELS(ic)); sym;
266 sym = setNextItem(IC_JTLABELS(ic)))
267 fprintf(of,"\t\t\t%s\n",sym->name);
270 PRINTFUNC(picGeneric)
273 printOperand(IC_RESULT(ic),of);
275 printOperand(IC_LEFT(ic),of);
276 fprintf(of," %s ",s);
277 printOperand(IC_RIGHT(ic),of);
281 PRINTFUNC(picGenericOne)
284 if ( IC_RESULT(ic) ) {
285 printOperand(IC_RESULT(ic),of);
290 fprintf (of,"%s ",s);
291 printOperand(IC_LEFT(ic),of);
294 if (! IC_RESULT(ic) && !IC_LEFT(ic))
303 printOperand(IC_RESULT(ic),of);
305 printOperand(IC_LEFT(ic),of);
306 printOperand(IC_RIGHT(ic),of);
315 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
318 printOperand(IC_RESULT(ic),of);
320 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
323 fprintf(of," %s ", s);
324 printOperand (IC_RIGHT(ic),of);
331 fprintf(of," %s($%d) :\n",IC_LABEL(ic)->name,IC_LABEL(ic)->key);
337 fprintf (of," goto %s($%d)\n", IC_LABEL(ic)->name,IC_LABEL(ic)->key);
344 printOperand(IC_COND(ic),of);
347 fprintf (of," == 0 goto %s($%d)\n",IC_FALSE(ic)->name,IC_FALSE(ic)->key);
349 fprintf (of," != 0 goto %s($%d)\n",IC_TRUE(ic)->name,IC_TRUE(ic)->key);
351 fprintf (of,"\tzzgoto %s\n",IC_FALSE(ic)->name);
357 fprintf(of,"%s",IC_INLINE(ic));
360 PRINTFUNC(picReceive)
362 printOperand(IC_RESULT(ic),of);
363 fprintf(of," = %s ",s);
364 printOperand(IC_LEFT(ic),of);
368 /*-----------------------------------------------------------------*/
369 /* piCode - prints one iCode */
370 /*-----------------------------------------------------------------*/
371 int piCode (void *item, FILE *of)
379 icTab = getTableEntry(ic->op) ;
380 fprintf(stdout,"%s(%d:%d:%d:%d:%d)\t",
381 ic->filename,ic->lineno,
382 ic->seq,ic->key,ic->depth,ic->supportRtn);
383 icTab->iCodePrint(of,ic,icTab->printName);
387 /*-----------------------------------------------------------------*/
388 /* printiCChain - prints intermediate code for humans */
389 /*-----------------------------------------------------------------*/
390 void printiCChain (iCode *icChain, FILE *of)
397 for ( loop = icChain ; loop ; loop = loop->next ) {
398 if ((icTab = getTableEntry (loop->op ))) {
399 fprintf(of,"%s(%d:%d:%d:%d:%d)\t",
400 loop->filename,loop->lineno,
401 loop->seq,loop->key,loop->depth,loop->supportRtn);
403 icTab->iCodePrint (of,loop,icTab->printName);
409 /*-----------------------------------------------------------------*/
410 /* newOperand - allocate, init & return a new iCode */
411 /*-----------------------------------------------------------------*/
412 operand *newOperand ()
416 op = Safe_calloc(1,sizeof(operand));
422 /*-----------------------------------------------------------------*/
423 /* newiCode - create and return a new iCode entry initialised */
424 /*-----------------------------------------------------------------*/
425 iCode *newiCode (int op, operand *left, operand *right)
429 ic = Safe_calloc(1,sizeof(iCode));
431 ic->lineno = lineno ;
432 ic->filename= filename ;
434 ic->level = scopeLevel;
436 ic->key= iCodeKey++ ;
443 /*-----------------------------------------------------------------*/
444 /* newiCode for conditional statements */
445 /*-----------------------------------------------------------------*/
446 iCode *newiCodeCondition (operand *condition,
452 ic = newiCode(IFX,NULL,NULL);
453 IC_COND(ic) = condition ;
454 IC_TRUE(ic) = trueLabel ;
455 IC_FALSE(ic) = falseLabel;
459 /*-----------------------------------------------------------------*/
460 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
461 /*-----------------------------------------------------------------*/
462 iCode *newiCodeLabelGoto (int op, symbol *label)
466 ic = newiCode(op,NULL,NULL);
468 ic->argLabel.label = label ;
470 IC_RIGHT(ic) = NULL ;
471 IC_RESULT(ic) = NULL ;
475 /*-----------------------------------------------------------------*/
476 /* newiTemp - allocate & return a newItemp Variable */
477 /*-----------------------------------------------------------------*/
478 symbol *newiTemp (char *s)
483 sprintf(buffer,"%s",s);
485 sprintf (buffer,"iTemp%d",iTempNum++);
486 itmp = newSymbol (buffer,1);
487 strcpy(itmp->rname,itmp->name);
493 /*-----------------------------------------------------------------*/
494 /* newiTempLabel - creates a temp variable label */
495 /*-----------------------------------------------------------------*/
496 symbol *newiTempLabel (char *s)
500 /* check if this alredy exists */
501 if (s && (itmplbl = findSym(LabelTab, NULL, s)))
505 itmplbl = newSymbol(s,1);
507 sprintf(buffer,"iTempLbl%d",iTempLblNum++);
508 itmplbl = newSymbol(buffer,1);
513 itmplbl->key = labelKey++ ;
514 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
518 /*-----------------------------------------------------------------*/
519 /* newiTempPreheaderLabel - creates a new preheader label */
520 /*-----------------------------------------------------------------*/
521 symbol *newiTempPreheaderLabel()
525 sprintf(buffer,"preHeaderLbl%d",iTempLblNum++);
526 itmplbl = newSymbol(buffer,1);
530 itmplbl->key = labelKey++ ;
531 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
536 /*-----------------------------------------------------------------*/
537 /* initiCode - initialises some iCode related stuff */
538 /*-----------------------------------------------------------------*/
544 /*-----------------------------------------------------------------*/
545 /* copyiCode - make a copy of the iCode given */
546 /*-----------------------------------------------------------------*/
547 iCode *copyiCode (iCode *ic)
549 iCode *nic = newiCode(ic->op,NULL,NULL);
551 nic->lineno = ic->lineno ;
552 nic->filename= ic->filename ;
553 nic->block = ic->block;
554 nic->level = ic->level;
556 /* deal with the special cases first */
559 IC_COND(nic) = operandFromOperand(IC_COND(ic));
560 IC_TRUE(nic) = IC_TRUE(ic);
561 IC_FALSE(nic)= IC_FALSE(ic);
565 IC_JTCOND(nic) = operandFromOperand(IC_JTCOND(ic));
566 IC_JTLABELS(nic) = IC_JTLABELS(ic);
571 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
572 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
573 IC_ARGS(nic) = IC_ARGS(ic);
577 IC_INLINE(nic) = IC_INLINE(ic);
581 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
582 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
583 IC_RIGHT(nic)= operandFromOperand(IC_RIGHT(ic));
589 /*-----------------------------------------------------------------*/
590 /* getTableEntry - gets the table entry for the given operator */
591 /*-----------------------------------------------------------------*/
592 iCodeTable *getTableEntry (int oper )
596 for ( i = 0 ; i < (sizeof(codeTable)/sizeof(iCodeTable)); i++ )
597 if (oper == codeTable[i].icode)
598 return &codeTable[i] ;
603 /*-----------------------------------------------------------------*/
604 /* newiTempOperand - new intermediate temp operand */
605 /*-----------------------------------------------------------------*/
606 operand *newiTempOperand (sym_link *type, char throwType)
609 operand *op = newOperand();
613 itmp = newiTemp(NULL);
615 etype = getSpec(type);
617 if (IS_LITERAL(etype) )
620 /* copy the type information */
622 itmp->etype = getSpec (itmp->type = (throwType ? type :
623 copyLinkChain(type)));
624 if (IS_LITERAL(itmp->etype)) {
625 SPEC_SCLS(itmp->etype) = S_REGISTER ;
626 SPEC_OCLS(itmp->etype) = reg;
629 op->operand.symOperand = itmp;
630 op->key = itmp->key = ++operandKey ;
634 /*-----------------------------------------------------------------*/
635 /* operandType - returns the type chain for an operand */
636 /*-----------------------------------------------------------------*/
637 sym_link *operandType (operand *op)
639 /* depending on type of operand */
643 return op->operand.valOperand->type ;
646 return op->operand.symOperand->type ;
649 return op->operand.typeOperand ;
651 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
652 " operand type not known ");
653 assert (0) ; /* should never come here */
654 /* Just to keep the compiler happy */
655 return (sym_link *)0;
659 /*-----------------------------------------------------------------*/
660 /* isParamterToCall - will return 1 if op is a parameter to args */
661 /*-----------------------------------------------------------------*/
662 int isParameterToCall (value *args, operand *op)
668 isSymbolEqual(op->operand.symOperand,tval->sym))
675 /*-----------------------------------------------------------------*/
676 /* isOperandGlobal - return 1 if operand is a global variable */
677 /*-----------------------------------------------------------------*/
678 int isOperandGlobal ( operand *op )
686 if (op->type == SYMBOL &&
687 (op->operand.symOperand->level == 0 ||
688 IS_STATIC(op->operand.symOperand->etype) ||
689 IS_EXTERN(op->operand.symOperand->etype))
696 /*-----------------------------------------------------------------*/
697 /* isOperandVolatile - return 1 if the operand is volatile */
698 /*-----------------------------------------------------------------*/
699 int isOperandVolatile ( operand *op , bool chkTemp)
704 if (IS_ITEMP(op) && !chkTemp)
707 opetype = getSpec(optype = operandType(op));
709 if (IS_PTR(optype) && DCL_PTR_VOLATILE(optype))
712 if (IS_VOLATILE(opetype))
717 /*-----------------------------------------------------------------*/
718 /* isOperandLiteral - returns 1 if an operand contains a literal */
719 /*-----------------------------------------------------------------*/
720 int isOperandLiteral ( operand *op )
727 opetype = getSpec (operandType(op));
729 if (IS_LITERAL(opetype))
734 /*-----------------------------------------------------------------*/
735 /* isOperandInFarSpace - will return true if operand is in farSpace*/
736 /*-----------------------------------------------------------------*/
737 bool isOperandInFarSpace (operand *op)
747 if (!IS_TRUE_SYMOP(op)) {
749 etype = SPIL_LOC(op)->etype;
755 etype = getSpec(operandType(op));
757 return (IN_FARSPACE(SPEC_OCLS(etype)) ? TRUE : FALSE);
760 /*-----------------------------------------------------------------*/
761 /* isOperandOnStack - will return true if operand is on stack */
762 /*-----------------------------------------------------------------*/
763 bool isOperandOnStack(operand *op)
773 etype = getSpec(operandType(op));
775 return ((IN_STACK(etype)) ? TRUE : FALSE);
778 /*-----------------------------------------------------------------*/
779 /* operandLitValue - literal value of an operand */
780 /*-----------------------------------------------------------------*/
781 double operandLitValue ( operand *op )
783 assert(isOperandLiteral(op));
785 return floatFromVal(op->operand.valOperand);
788 /*-----------------------------------------------------------------*/
789 /* operandOperation - perforoms operations on operands */
790 /*-----------------------------------------------------------------*/
791 operand *operandOperation (operand *left,operand *right,
792 int op, sym_link *type)
794 operand *retval = (operand *)0;
796 assert(isOperandLiteral(left));
798 assert(isOperandLiteral(right));
802 retval = operandFromValue (valCastLiteral(type,
803 operandLitValue(left) +
804 operandLitValue(right)));
807 retval = operandFromValue(valCastLiteral(type,
808 operandLitValue(left) -
809 operandLitValue(right)));
812 retval = operandFromValue(valCastLiteral(type,
813 operandLitValue(left) *
814 operandLitValue(right)));
817 if ((unsigned long) operandLitValue(right) == 0){
818 werror(E_DIVIDE_BY_ZERO);
823 retval = operandFromValue (valCastLiteral(type,
824 operandLitValue(left) /
825 operandLitValue(right)));
828 if ((unsigned long) operandLitValue(right) == 0){
829 werror(E_DIVIDE_BY_ZERO);
833 retval = operandFromLit ((unsigned long) operandLitValue(left) %
834 (unsigned long) operandLitValue(right));
837 retval = operandFromLit ((unsigned long) operandLitValue(left) <<
838 (unsigned long) operandLitValue(right));
841 retval = operandFromLit ((unsigned long) operandLitValue(left) >>
842 (unsigned long) operandLitValue(right));
845 retval = operandFromLit (operandLitValue(left) ==
846 operandLitValue(right));
849 retval = operandFromLit (operandLitValue(left) <
850 operandLitValue(right));
853 retval = operandFromLit (operandLitValue(left) <=
854 operandLitValue(right));
857 retval = operandFromLit (operandLitValue(left) !=
858 operandLitValue(right));
861 retval = operandFromLit (operandLitValue(left) >
862 operandLitValue(right));
865 retval = operandFromLit (operandLitValue(left) >=
866 operandLitValue(right));
869 retval = operandFromLit ((unsigned long) operandLitValue(left) &
870 (unsigned long) operandLitValue(right));
873 retval = operandFromLit ((unsigned long) operandLitValue(left) |
874 (unsigned long) operandLitValue(right));
877 retval = operandFromLit ((unsigned long) operandLitValue(left) ^
878 (unsigned long) operandLitValue(right));
881 retval = operandFromLit (operandLitValue(left) &&
882 operandLitValue(right));
885 retval = operandFromLit (operandLitValue(left) ||
886 operandLitValue(right));
890 long i = operandLitValue(left);
892 retval = operandFromLit ((i >> (getSize(operandType(left))*8 - 1)) |
898 long i = operandLitValue(left);
900 retval = operandFromLit ((i << (getSize(operandType(left))*8 - 1)) |
906 retval = operandFromLit(-1 * operandLitValue(left));
910 retval = operandFromLit(~ ((long) operandLitValue(left)));
914 retval = operandFromLit(! operandLitValue(left));
918 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
919 " operandOperation invalid operator ");
927 /*-----------------------------------------------------------------*/
928 /* isOperandEqual - compares two operand & return 1 if they r = */
929 /*-----------------------------------------------------------------*/
930 int isOperandEqual (operand *left, operand *right)
932 /* if the pointers are equal then they are equal */
936 /* if either of them null then false */
937 if ( !left || !right)
940 if (left->type != right->type)
943 if (IS_SYMOP(left) && IS_SYMOP(right))
944 return left->key == right->key ;
946 /* if types are the same */
947 switch (left->type) {
949 return isSymbolEqual(left->operand.symOperand,
950 right->operand.symOperand);
952 return (floatFromVal(left->operand.valOperand) ==
953 floatFromVal(right->operand.valOperand));
955 if (checkType(left->operand.typeOperand,
956 right->operand.typeOperand) == 1)
963 /*-----------------------------------------------------------------*/
964 /* isiCodeEqual - comapres two iCodes are returns true if yes */
965 /*-----------------------------------------------------------------*/
966 int isiCodeEqual (iCode *left, iCode *right)
968 /* if the same pointer */
972 /* if either of them null */
976 /* if operand are the same */
977 if ( left->op == right->op ) {
979 /* compare all the elements depending on type */
980 if (left->op != IFX ) {
981 if (!isOperandEqual(IC_LEFT(left),IC_LEFT(right)))
983 if (!isOperandEqual(IC_RIGHT(left),IC_RIGHT(right)))
987 if (!isOperandEqual(IC_COND(left),IC_COND(right)))
989 if (!isSymbolEqual (IC_TRUE(left),IC_TRUE(right)))
991 if (!isSymbolEqual(IC_FALSE(left),IC_FALSE(right)))
999 /*-----------------------------------------------------------------*/
1000 /* newiTempFromOp - create a temp Operand with same attributes */
1001 /*-----------------------------------------------------------------*/
1002 operand *newiTempFromOp (operand *op)
1012 nop = newiTempOperand(operandType(op),TRUE);
1013 nop->isaddr = op->isaddr ;
1014 nop->isvolatile = op->isvolatile ;
1015 nop->isGlobal = op->isGlobal ;
1016 nop->isLiteral= op->isLiteral ;
1017 nop->noSpilLoc= op->noSpilLoc;
1018 nop->usesDefs = op->usesDefs;
1019 nop->isParm = op->isParm;
1020 nop->parmBytes = op->parmBytes;
1024 /*-----------------------------------------------------------------*/
1025 /* operand from operand - creates an operand holder for the type */
1026 /*-----------------------------------------------------------------*/
1027 operand *operandFromOperand (operand *op)
1034 nop->type = op->type;
1035 nop->isaddr = op->isaddr ;
1036 nop->key = op->key ;
1037 nop->isvolatile = op->isvolatile ;
1038 nop->isGlobal = op->isGlobal ;
1039 nop->isLiteral= op->isLiteral ;
1040 nop->noSpilLoc= op->noSpilLoc;
1041 nop->usesDefs = op->usesDefs;
1042 nop->isParm = op->isParm;
1043 nop->parmBytes = op->parmBytes;
1045 switch (nop->type) {
1047 nop->operand.symOperand = op->operand.symOperand ;
1050 nop->operand.valOperand = op->operand.valOperand;
1053 nop->operand.typeOperand = op->operand.typeOperand ;
1060 /*-----------------------------------------------------------------*/
1061 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1062 /*-----------------------------------------------------------------*/
1063 operand *opFromOpWithDU (operand *op, bitVect *defs, bitVect *uses)
1065 operand *nop = operandFromOperand(op);
1067 if (nop->type == SYMBOL) {
1068 OP_SYMBOL(nop)->defs = bitVectCopy(defs);
1069 OP_SYMBOL(nop)->uses = bitVectCopy(uses);
1075 /*-----------------------------------------------------------------*/
1076 /* operandFromSymbol - creates an operand from a symbol */
1077 /*-----------------------------------------------------------------*/
1078 operand *operandFromSymbol (symbol *sym)
1083 /* if the symbol's type is a literal */
1084 /* then it is an enumerator type */
1085 if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype))
1086 return operandFromValue (valFromType(sym->etype));
1089 sym->key = ++operandKey ;
1091 /* if this an implicit variable, means struct/union */
1092 /* member so just return it */
1093 if (sym->implicit || IS_FUNC(sym->type)) {
1096 op->operand.symOperand = sym;
1097 op->key = sym->key ;
1098 op->isvolatile = isOperandVolatile(op,TRUE);
1099 op->isGlobal = isOperandGlobal(op);
1100 op->parmBytes = sym->argStack;
1104 /* under the following conditions create a
1105 register equivalent for a local symbol */
1106 if (sym->level && sym->etype && SPEC_OCLS(sym->etype) &&
1107 (IN_FARSPACE(SPEC_OCLS(sym->etype)) && (!IS_DS390_PORT)) &&
1108 options.stackAuto == 0)
1111 if (!IS_AGGREGATE(sym->type) && /* not an aggregate */
1112 !IS_FUNC(sym->type) && /* not a function */
1113 !sym->_isparm && /* not a parameter */
1114 sym->level && /* is a local variable */
1115 !sym->addrtaken && /* whose address has not been taken */
1116 !sym->reqv && /* does not already have a register euivalence */
1117 !IS_VOLATILE(sym->etype) && /* not declared as volatile */
1118 !IS_STATIC(sym->etype) && /* and not declared static */
1119 !sym->islbl && /* not a label */
1120 ok && /* farspace check */
1121 !IS_BITVAR(sym->etype) /* not a bit variable */
1124 /* we will use it after all optimizations
1125 and before liveRange calculation */
1126 sym->reqv = newiTempOperand(sym->type,0);
1127 sym->reqv->key = sym->key ;
1128 OP_SYMBOL(sym->reqv)->key = sym->key;
1129 OP_SYMBOL(sym->reqv)->isreqv = 1;
1130 OP_SYMBOL(sym->reqv)->islocal = 1;
1131 SPIL_LOC(sym->reqv) = sym;
1134 if (!IS_AGGREGATE(sym->type)) {
1137 op->operand.symOperand = sym;
1140 op->isvolatile = isOperandVolatile(op,TRUE);
1141 op->isGlobal = isOperandGlobal(op);
1142 op->isPtr = IS_PTR(operandType(op));
1143 op->isParm = sym->_isparm ;
1148 /* itemp = &[_symbol] */
1150 ic = newiCode(ADDRESS_OF,newOperand(),NULL);
1151 IC_LEFT(ic)->type = SYMBOL ;
1152 IC_LEFT(ic)->operand.symOperand = sym ;
1153 IC_LEFT(ic)->key = sym->key;
1154 (IC_LEFT(ic))->isvolatile = isOperandVolatile(IC_LEFT(ic),TRUE);
1155 (IC_LEFT(ic))->isGlobal = isOperandGlobal(IC_LEFT(ic));
1156 IC_LEFT(ic)->isPtr = IS_PTR(operandType(IC_LEFT(ic)));
1159 IC_RESULT(ic) = newiTempOperand(sym->type,0);
1160 if (IS_ARRAY(sym->type)) {
1161 IC_RESULT(ic) = geniCodeArray2Ptr (IC_RESULT(ic));
1162 IC_RESULT(ic)->isaddr = 0;
1164 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(sym->type));
1166 IC_RESULT(ic)->operand.symOperand->args = sym->args;
1170 return IC_RESULT(ic) ;
1173 /*-----------------------------------------------------------------*/
1174 /* operandFromValue - creates an operand from value */
1175 /*-----------------------------------------------------------------*/
1176 operand *operandFromValue (value *val)
1180 /* if this is a symbol then do the symbol thing */
1182 return operandFromSymbol (val->sym);
1184 /* this is not a symbol */
1187 op->operand.valOperand = val ;
1188 op->isLiteral = isOperandLiteral(op);
1192 /*-----------------------------------------------------------------*/
1193 /* operandFromLink - operand from typeChain */
1194 /*-----------------------------------------------------------------*/
1195 operand *operandFromLink (sym_link *type)
1199 /* operand from sym_link */
1205 op->operand.typeOperand = copyLinkChain(type);
1209 /*-----------------------------------------------------------------*/
1210 /* operandFromLit - makes an operand from a literal value */
1211 /*-----------------------------------------------------------------*/
1212 operand *operandFromLit ( float i)
1214 return operandFromValue (valueFromLit (i));
1217 /*-----------------------------------------------------------------*/
1218 /* operandFromAst - creates an operand from an ast */
1219 /*-----------------------------------------------------------------*/
1220 operand *operandFromAst ( ast *tree )
1226 /* depending on type do */
1227 switch (tree->type ) {
1229 return ast2iCode (tree) ;
1233 return operandFromValue(tree->opval.val) ;
1237 return operandFromLink (tree->opval.lnk) ;
1241 /* Just to keep the comiler happy */
1242 return (operand *)0;
1245 /*-----------------------------------------------------------------*/
1246 /* setOperandType - sets the operand's type to the given type */
1247 /*-----------------------------------------------------------------*/
1248 void setOperandType (operand *op, sym_link *type)
1250 /* depending on the type of operand */
1254 op->operand.valOperand->etype =
1255 getSpec( op->operand.valOperand->type =
1256 copyLinkChain (type )) ;
1260 if (op->operand.symOperand->isitmp )
1261 op->operand.symOperand->etype =
1262 getSpec( op->operand.symOperand->type =
1263 copyLinkChain (type )) ;
1265 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
1266 "attempt to modify type of source");
1270 op->operand.typeOperand = copyLinkChain (type);
1276 /*-----------------------------------------------------------------*/
1277 /* perform "usual unary conversions" */
1278 /*-----------------------------------------------------------------*/
1279 operand *usualUnaryConversions(operand *op)
1281 if (IS_INTEGRAL(operandType(op)))
1283 if (getSize(operandType(op)) < INTSIZE)
1286 return geniCodeCast(INTTYPE,op,TRUE);
1292 /*-----------------------------------------------------------------*/
1293 /* perform "usual binary conversions" */
1294 /*-----------------------------------------------------------------*/
1295 sym_link * usualBinaryConversions(operand **op1, operand **op2)
1297 if (!options.ANSIint)
1299 /* "Classic" SDCC behavior. */
1301 sym_link *rtype = operandType(*op2);
1302 sym_link *ltype = operandType(*op1);
1304 ctype = computeType(ltype,rtype);
1305 *op1 = geniCodeCast(ctype,*op1,TRUE);
1306 *op2= geniCodeCast(ctype,*op2,TRUE);
1311 *op1 = usualUnaryConversions(*op1);
1312 *op2 = usualUnaryConversions(*op2);
1314 /* Try to make the two operands of the same type, following
1315 * the "usual binary conversions" promotion rules.
1317 * NB: floating point types are not yet properly handled; we
1318 * follow the "classic" behavior.
1321 if (IS_FLOAT(operandType(*op1)) || IS_FLOAT(operandType(*op2)))
1323 return newFloatLink();
1326 if (!IS_INTEGRAL(operandType(*op1)) || !IS_INTEGRAL(operandType(*op2)))
1328 /* if either is not an integer type, we're done. */
1329 return copyLinkChain(operandType(*op1)); /* Punt! we should never get here. */
1332 /* If either is an unsigned long, make sure both are. */
1333 if (SPEC_USIGN(operandType(*op1)) && IS_LONG(operandType(*op1)))
1335 if (!SPEC_USIGN(operandType(*op2)) || !IS_LONG(operandType(*op2)))
1337 *op2 = geniCodeCast(ULONGTYPE,*op2,TRUE);
1339 return copyLinkChain(operandType(*op1));
1342 if (SPEC_USIGN(operandType(*op2)) && IS_LONG(operandType(*op2)))
1344 if (!SPEC_USIGN(operandType(*op1)) || !IS_LONG(operandType(*op1)))
1346 *op1 = geniCodeCast(ULONGTYPE,*op1,TRUE);
1348 return copyLinkChain(operandType(*op2));
1351 /* Next, if one is long and the other is int (signed or un),
1352 * cast both to long.
1354 * Note that because in our environment a long can hold all
1355 * the values of an unsigned int, the "long/unsigned int" pair
1356 * in the ANSI conversion table is unnecessary; this test
1357 * handles that case implicitly.
1359 if (IS_LONG(operandType(*op1)))
1361 /* NB: because of the unary conversions, op2 cannot
1362 * be smaller than int. Therefore, if it is not
1363 * long, it is a regular int.
1365 if (!IS_LONG(operandType(*op2)))
1367 *op2 = geniCodeCast(LONGTYPE,*op2,TRUE);
1369 return copyLinkChain(operandType(*op1));
1372 if (IS_LONG(operandType(*op2)))
1374 /* NB: because of the unary conversions, op2 cannot
1375 * be smaller than int. Therefore, if it is not
1376 * long, it is a regular int.
1378 if (!IS_LONG(operandType(*op1)))
1380 *op1 = geniCodeCast(LONGTYPE,*op1,TRUE);
1382 return copyLinkChain(operandType(*op2));
1385 /* All right, neither is long; they must both be integers.
1387 * Only remaining issue is signed vs. unsigned; if one is unsigned
1388 * and the other isn't, convert both to unsigned.
1390 if (SPEC_USIGN(operandType(*op1)))
1392 if (!SPEC_USIGN(operandType(*op2)))
1394 *op2 = geniCodeCast(UINTTYPE,*op2,TRUE);
1396 return copyLinkChain(operandType(*op1));
1399 if (SPEC_USIGN(operandType(*op2)))
1401 if (!SPEC_USIGN(operandType(*op1)))
1403 *op1 = geniCodeCast(UINTTYPE,*op1,TRUE);
1405 return copyLinkChain(operandType(*op2));
1409 return copyLinkChain(operandType(*op1));
1413 /*-----------------------------------------------------------------*/
1414 /* geniCodeValueAtAddress - generate intermeditate code for value */
1416 /*-----------------------------------------------------------------*/
1417 operand *geniCodeRValue (operand *op, bool force)
1420 sym_link *type = operandType(op);
1421 sym_link *etype= getSpec(type);
1423 /* if this is an array & already */
1424 /* an address then return this */
1425 if (IS_AGGREGATE(type) ||
1426 (IS_PTR(type) && !force && !op->isaddr))
1427 return operandFromOperand(op);
1429 /* if this is not an address then must be */
1430 /* rvalue already so return this one */
1434 /* if this is not a temp symbol then */
1435 if (!IS_ITEMP(op) &&
1437 !IN_FARSPACE(SPEC_OCLS(etype))) {
1438 op = operandFromOperand(op);
1443 if (IS_SPEC(type) &&
1444 IS_TRUE_SYMOP(op) &&
1445 (!IN_FARSPACE(SPEC_OCLS(etype)) || IS_DS390_PORT)) {
1446 op = operandFromOperand(op);
1451 ic = newiCode(GET_VALUE_AT_ADDRESS,op,NULL);
1452 if (IS_PTR(type) && op->isaddr && force)
1455 type = copyLinkChain(type);
1457 IC_RESULT(ic) = newiTempOperand (type,1);
1458 IC_RESULT(ic)->isaddr = 0;
1460 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1462 /* if the right is a symbol */
1463 if (op->type == SYMBOL)
1464 IC_RESULT(ic)->operand.symOperand->args =
1465 op->operand.symOperand->args ;
1468 return IC_RESULT(ic) ;
1471 /*-----------------------------------------------------------------*/
1472 /* geniCodeCast - changes the value from one type to another */
1473 /*-----------------------------------------------------------------*/
1474 operand *geniCodeCast (sym_link *type, operand *op, bool implicit)
1478 sym_link *opetype = getSpec(optype = operandType(op));
1481 /* one of them has size zero then error */
1482 if (IS_VOID(optype)) {
1483 werror(E_CAST_ZERO);
1487 /* if the operand is already the desired type then do nothing */
1488 if ( checkType (type,optype) == 1)
1491 /* if this is a literal then just change the type & return */
1492 if (IS_LITERAL(opetype) && op->type == VALUE && !IS_PTR(type) && !IS_PTR(optype))
1493 return operandFromValue(valCastLiteral(type,
1494 operandLitValue(op)));
1496 /* if casting to some pointer type &&
1497 the destination is not a generic pointer
1498 then give a warning : (only for implicit casts)*/
1499 if (IS_PTR(optype) && implicit &&
1500 (DCL_TYPE(optype) != DCL_TYPE(type)) &&
1502 werror(E_INCOMPAT_CAST);
1503 werror(E_CONTINUE,"from type '");
1504 printTypeChain(optype,stderr);fprintf(stderr,"' to type '");
1505 printTypeChain(type,stderr);fprintf(stderr,"'\n");
1508 /* if they are the same size create an assignment */
1509 if (getSize(type) == getSize(optype) &&
1510 !IS_BITFIELD(type) &&
1512 !IS_FLOAT(optype) &&
1513 ((IS_SPEC(type) && IS_SPEC(optype)) ||
1514 (!IS_SPEC(type) && !IS_SPEC(optype)))) {
1516 ic = newiCode('=',NULL,op);
1517 IC_RESULT(ic) = newiTempOperand(type,0);
1518 SPIL_LOC(IC_RESULT(ic)) =
1519 (IS_TRUE_SYMOP(op) ? OP_SYMBOL(op) : NULL);
1520 IC_RESULT(ic)->isaddr = 0;
1522 ic = newiCode(CAST,operandFromLink(type),
1523 geniCodeRValue(op,FALSE));
1525 IC_RESULT(ic)= newiTempOperand(type,0);
1528 /* preserve the storage class & output class */
1529 /* of the original variable */
1530 restype = getSpec(operandType(IC_RESULT(ic)));
1531 SPEC_SCLS(restype) = SPEC_SCLS(opetype);
1532 SPEC_OCLS(restype) = SPEC_OCLS(opetype);
1535 return IC_RESULT(ic) ;
1538 /*-----------------------------------------------------------------*/
1539 /* geniCodeLabel - will create a Label */
1540 /*-----------------------------------------------------------------*/
1541 void geniCodeLabel (symbol *label)
1545 ic = newiCodeLabelGoto(LABEL,label);
1549 /*-----------------------------------------------------------------*/
1550 /* geniCodeGoto - will create a Goto */
1551 /*-----------------------------------------------------------------*/
1552 void geniCodeGoto (symbol *label)
1556 ic = newiCodeLabelGoto(GOTO,label);
1560 /*-----------------------------------------------------------------*/
1561 /* geniCodeMultiply - gen intermediate code for multiplication */
1562 /*-----------------------------------------------------------------*/
1563 operand *geniCodeMultiply (operand *left, operand *right,bool ptrSizeCalculation)
1571 /* if they are both literal then we know the result */
1572 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1573 return operandFromValue (valMult(left->operand.valOperand,
1574 right->operand.valOperand));
1577 //Force 1 byte * 1 byte = 2 bytes result if we are computing ptr size
1578 if ((ptrSizeCalculation)&&(1==getSize(rtype))&&
1579 (1==getSize(ltype))) {
1580 saveOption = options.ANSIint;
1581 options.ANSIint = 0;
1582 resType = usualBinaryConversions(&left, &right);
1583 ltype = operandType(left);
1584 rtype = operandType(right);
1585 SPEC_SHORT(getSpec(resType)) = 0;
1586 options.ANSIint = saveOption;
1589 resType = usualBinaryConversions(&left, &right);
1591 /* if the right is a literal & power of 2 */
1592 /* then make it a left shift */
1593 /*If we are computing ptr size then normal multiplication*/
1594 /*code generated for 1 byte * 1 byte literal = 2 bytes result is more efficient in most cases*/
1595 /*than 2 bytes result = 2 bytes << literal if port as 1 byte muldiv*/
1596 if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
1597 !((ptrSizeCalculation)&&(getSize(resType)!=getSize(ltype))&&(1==port->muldiv.native_below))&&
1598 (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand))))
1600 if((ptrSizeCalculation)&&(getSize(resType)!=getSize(ltype))){
1601 /* LEFT_OP need same size for left and result, */
1602 left = geniCodeCast(resType,left,TRUE);
1603 ltype = operandType(left);
1605 ic = newiCode(LEFT_OP, left,operandFromLit(p2)); /* left shift */
1608 ic = newiCode('*',left,right); /* normal multiplication */
1609 /* if the size left or right > 1 then support routine */
1610 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1614 IC_RESULT(ic) = newiTempOperand(resType,1);
1617 return IC_RESULT(ic) ;
1620 /*-----------------------------------------------------------------*/
1621 /* geniCodeDivision - gen intermediate code for division */
1622 /*-----------------------------------------------------------------*/
1623 operand *geniCodeDivision (operand *left, operand *right)
1628 sym_link *rtype = operandType(right);
1629 sym_link *retype= getSpec(rtype);
1630 sym_link *ltype = operandType(left);
1631 sym_link *letype= getSpec(ltype);
1633 resType = usualBinaryConversions(&left, &right);
1635 /* if the right is a literal & power of 2 */
1636 /* then make it a right shift */
1637 if (IS_LITERAL(retype) &&
1638 !IS_FLOAT(letype) &&
1639 (p2 = powof2 ((unsigned long)
1640 floatFromVal(right->operand.valOperand))))
1641 ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
1643 ic = newiCode('/',left,right); /* normal division */
1644 /* if the size left or right > 1 then support routine */
1645 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1648 IC_RESULT(ic) = newiTempOperand(resType,0);
1651 return IC_RESULT(ic) ;
1653 /*-----------------------------------------------------------------*/
1654 /* geniCodeModulus - gen intermediate code for modulus */
1655 /*-----------------------------------------------------------------*/
1656 operand *geniCodeModulus (operand *left, operand *right)
1662 /* if they are both literal then we know the result */
1663 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1664 return operandFromValue (valMod(left->operand.valOperand,
1665 right->operand.valOperand));
1667 resType = usualBinaryConversions(&left, &right);
1669 /* now they are the same size */
1670 ic = newiCode('%',left,right);
1672 /* if the size left or right > 1 then support routine */
1673 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1675 IC_RESULT(ic) = newiTempOperand(resType,0);
1678 return IC_RESULT(ic) ;
1681 /*-----------------------------------------------------------------*/
1682 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1683 /*-----------------------------------------------------------------*/
1684 operand *geniCodePtrPtrSubtract (operand *left, operand *right)
1690 /* if they are both literals then */
1691 if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
1692 result = operandFromValue (valMinus(left->operand.valOperand,
1693 right->operand.valOperand));
1697 ic = newiCode('-',left,right);
1699 IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
1703 return geniCodeDivision (result,
1704 operandFromLit(getSize(ltype->next)));
1707 /*-----------------------------------------------------------------*/
1708 /* geniCodeSubtract - generates code for subtraction */
1709 /*-----------------------------------------------------------------*/
1710 operand *geniCodeSubtract (operand *left, operand *right)
1717 /* if they both pointers then */
1718 if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
1719 (IS_PTR(rtype) || IS_ARRAY(rtype)))
1720 return geniCodePtrPtrSubtract (left,right);
1722 /* if they are both literal then we know the result */
1723 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1724 && left->isLiteral && right->isLiteral)
1725 return operandFromValue (valMinus(left->operand.valOperand,
1726 right->operand.valOperand));
1728 /* if left is an array or pointer */
1729 if ( IS_PTR(ltype) || IS_ARRAY(ltype) ) {
1730 isarray = left->isaddr ;
1731 right = geniCodeMultiply (right,
1732 operandFromLit(getSize(ltype->next)),TRUE);
1733 resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
1735 else { /* make them the same size */
1736 resType = usualBinaryConversions(&left, &right);
1739 ic = newiCode('-',left,right);
1741 IC_RESULT(ic)= newiTempOperand(resType,1);
1742 IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
1744 /* if left or right is a float */
1745 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1749 return IC_RESULT(ic) ;
1752 /*-----------------------------------------------------------------*/
1753 /* geniCodeAdd - generates iCode for addition */
1754 /*-----------------------------------------------------------------*/
1755 operand *geniCodeAdd (operand *left, operand *right )
1763 /* if left is an array then array access */
1764 if (IS_ARRAY(ltype))
1765 return geniCodeArray (left,right);
1767 /* if the right side is LITERAL zero */
1768 /* return the left side */
1769 if (IS_LITERAL(retype) && right->isLiteral && !floatFromVal(valFromType(retype)))
1772 /* if left is literal zero return right */
1773 if (IS_LITERAL(letype) && left->isLiteral && !floatFromVal(valFromType(letype)))
1776 /* if left is an array or pointer then size */
1777 if (IS_PTR(ltype)) {
1779 isarray = left->isaddr;
1781 operandFromLit(getSize(ltype->next));
1783 right = geniCodeMultiply (right ,size,(getSize(ltype)!= 1));
1785 resType = copyLinkChain(ltype);
1787 else { /* make them the same size */
1788 resType = usualBinaryConversions(&left, &right);
1791 /* if they are both literals then we know */
1792 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1793 && left->isLiteral && right->isLiteral)
1794 return operandFromValue (valPlus(valFromType(letype),
1795 valFromType(retype)));
1797 ic = newiCode('+',left,right);
1799 IC_RESULT(ic) = newiTempOperand(resType,1);
1800 IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
1802 /* if left or right is a float then support
1804 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1809 return IC_RESULT(ic) ;
1813 /*-----------------------------------------------------------------*/
1814 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1815 /*-----------------------------------------------------------------*/
1816 sym_link *aggrToPtr ( sym_link *type, bool force)
1822 if (IS_PTR(type) && !force)
1825 etype = getSpec(type);
1829 /* if the output class is generic */
1830 if ((DCL_TYPE(ptype) = PTR_TYPE(SPEC_OCLS(etype))) == CPOINTER)
1831 DCL_PTR_CONST(ptype) = port->mem.code_ro;
1833 /* if the variable was declared a constant */
1834 /* then the pointer points to a constant */
1835 if (IS_CONSTANT(etype) )
1836 DCL_PTR_CONST(ptype) = 1;
1838 /* the variable was volatile then pointer to volatile */
1839 if (IS_VOLATILE(etype))
1840 DCL_PTR_VOLATILE(ptype) = 1;
1844 /*-----------------------------------------------------------------*/
1845 /* geniCodeArray2Ptr - array to pointer */
1846 /*-----------------------------------------------------------------*/
1847 operand *geniCodeArray2Ptr (operand *op)
1849 sym_link *optype = operandType(op);
1850 sym_link *opetype = getSpec(optype);
1852 /* set the pointer depending on the storage class */
1853 if ((DCL_TYPE(optype) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1854 DCL_PTR_CONST(optype) = port->mem.code_ro;
1857 /* if the variable was declared a constant */
1858 /* then the pointer points to a constant */
1859 if (IS_CONSTANT(opetype) )
1860 DCL_PTR_CONST(optype) = 1;
1862 /* the variable was volatile then pointer to volatile */
1863 if (IS_VOLATILE(opetype))
1864 DCL_PTR_VOLATILE(optype) = 1;
1870 /*-----------------------------------------------------------------*/
1871 /* geniCodeArray - array access */
1872 /*-----------------------------------------------------------------*/
1873 operand *geniCodeArray (operand *left,operand *right)
1876 sym_link *ltype = operandType(left);
1878 if (IS_PTR(ltype)) {
1879 if (IS_PTR(ltype->next) && left->isaddr)
1881 left = geniCodeRValue(left,FALSE);
1883 return geniCodeDerefPtr(geniCodeAdd(left,right));
1887 right = geniCodeMultiply(right,
1888 operandFromLit(getSize(ltype->next)),TRUE);
1890 /* we can check for limits here */
1891 if (isOperandLiteral(right) &&
1894 (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
1895 werror(E_ARRAY_BOUND);
1896 right = operandFromLit(0);
1899 ic = newiCode('+',left,right);
1901 IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) &&
1902 !IS_AGGREGATE(ltype->next) &&
1903 !IS_PTR(ltype->next))
1904 ? ltype : ltype->next),0);
1906 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
1908 return IC_RESULT(ic) ;
1911 /*-----------------------------------------------------------------*/
1912 /* geniCodeStruct - generates intermediate code for structres */
1913 /*-----------------------------------------------------------------*/
1914 operand *geniCodeStruct (operand *left, operand *right, bool islval)
1917 sym_link *type = operandType(left);
1918 sym_link *etype = getSpec(type);
1920 symbol *element = getStructElement(SPEC_STRUCT(etype),
1921 right->operand.symOperand);
1923 /* add the offset */
1924 ic = newiCode('+',left,operandFromLit(element->offset));
1926 IC_RESULT(ic) = newiTempOperand(element->type,0);
1928 /* preserve the storage & output class of the struct */
1929 /* as well as the volatile attribute */
1930 retype = getSpec(operandType(IC_RESULT(ic)));
1931 SPEC_SCLS(retype) = SPEC_SCLS(etype);
1932 SPEC_OCLS(retype) = SPEC_OCLS(etype);
1933 SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);
1935 if (IS_PTR(element->type))
1936 setOperandType(IC_RESULT(ic),aggrToPtr(operandType(IC_RESULT(ic)),TRUE));
1938 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(element->type));
1942 return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
1945 /*-----------------------------------------------------------------*/
1946 /* geniCodePostInc - generate int code for Post increment */
1947 /*-----------------------------------------------------------------*/
1948 operand *geniCodePostInc (operand *op)
1952 sym_link *optype = operandType(op);
1954 operand *rv = (IS_ITEMP(op) ?
1955 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1957 sym_link *rvtype = operandType(rv);
1960 /* if this is not an address we have trouble */
1961 if ( ! op->isaddr ) {
1962 werror (E_LVALUE_REQUIRED,"++");
1966 rOp = newiTempOperand(rvtype,0);
1972 geniCodeAssign(rOp,rv,0);
1974 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1975 if (IS_FLOAT(rvtype))
1976 ic = newiCode('+',rv,operandFromValue(constFloatVal("1.0")));
1978 ic = newiCode('+',rv,operandFromLit(size));
1980 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1983 geniCodeAssign(op,result,0);
1989 /*-----------------------------------------------------------------*/
1990 /* geniCodePreInc - generate code for preIncrement */
1991 /*-----------------------------------------------------------------*/
1992 operand *geniCodePreInc (operand *op)
1995 sym_link *optype = operandType(op);
1996 operand *rop = (IS_ITEMP(op) ?
1997 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1999 sym_link *roptype = operandType(rop);
2003 if ( ! op->isaddr ) {
2004 werror(E_LVALUE_REQUIRED,"++");
2009 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
2010 if (IS_FLOAT(roptype))
2011 ic = newiCode('+',rop,operandFromValue(constFloatVal("1.0")));
2013 ic = newiCode('+',rop,operandFromLit(size));
2014 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
2018 return geniCodeAssign(op,result,0) ;
2021 /*-----------------------------------------------------------------*/
2022 /* geniCodePostDec - generates code for Post decrement */
2023 /*-----------------------------------------------------------------*/
2024 operand *geniCodePostDec (operand *op)
2028 sym_link *optype = operandType(op);
2030 operand *rv = (IS_ITEMP(op) ?
2031 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
2033 sym_link *rvtype = operandType(rv);
2036 /* if this is not an address we have trouble */
2037 if ( ! op->isaddr ) {
2038 werror (E_LVALUE_REQUIRED,"++");
2042 rOp = newiTempOperand(rvtype,0);
2048 geniCodeAssign(rOp,rv,0);
2050 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
2051 if (IS_FLOAT(rvtype))
2052 ic = newiCode('-',rv,operandFromValue(constFloatVal("1.0")));
2054 ic = newiCode('-',rv,operandFromLit(size));
2056 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
2059 geniCodeAssign(op,result,0);
2065 /*-----------------------------------------------------------------*/
2066 /* geniCodePreDec - generate code for pre decrement */
2067 /*-----------------------------------------------------------------*/
2068 operand *geniCodePreDec (operand *op)
2071 sym_link *optype = operandType(op);
2072 operand *rop = (IS_ITEMP(op) ?
2073 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
2075 sym_link *roptype = operandType(rop);
2079 if ( ! op->isaddr ) {
2080 werror(E_LVALUE_REQUIRED,"++");
2085 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
2086 if (IS_FLOAT(roptype))
2087 ic = newiCode('-',rop,operandFromValue(constFloatVal("1.0")));
2089 ic = newiCode('-',rop,operandFromLit(size));
2090 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
2094 return geniCodeAssign(op,result,0) ;
2098 /*-----------------------------------------------------------------*/
2099 /* geniCodeBitwise - gen int code for bitWise operators */
2100 /*-----------------------------------------------------------------*/
2101 operand *geniCodeBitwise (operand *left, operand *right,
2102 int oper, sym_link *resType)
2106 left = geniCodeCast(resType,left,TRUE);
2107 right= geniCodeCast(resType,right,TRUE);
2109 ic = newiCode(oper,left,right);
2110 IC_RESULT(ic) = newiTempOperand(resType,0);
2113 return IC_RESULT(ic) ;
2116 /*-----------------------------------------------------------------*/
2117 /* geniCodeAddressOf - gens icode for '&' address of operator */
2118 /*-----------------------------------------------------------------*/
2119 operand *geniCodeAddressOf (operand *op)
2123 sym_link *optype = operandType(op);
2124 sym_link *opetype= getSpec(optype);
2126 /* lvalue check already done in decorateType */
2127 /* this must be a lvalue */
2128 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2129 /* werror (E_LVALUE_REQUIRED,"&"); */
2134 p->class = DECLARATOR ;
2136 /* set the pointer depending on the storage class */
2137 if ((DCL_TYPE(p) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
2138 DCL_PTR_CONST(p) = port->mem.code_ro;
2140 /* make sure we preserve the const & volatile */
2141 if (IS_CONSTANT(opetype))
2142 DCL_PTR_CONST(p) = 1;
2144 if (IS_VOLATILE(opetype))
2145 DCL_PTR_VOLATILE(p) = 1;
2147 p->next = copyLinkChain(optype);
2149 /* if already a temp */
2151 setOperandType (op,p);
2156 /* other wise make this of the type coming in */
2157 ic = newiCode(ADDRESS_OF,op,NULL);
2158 IC_RESULT(ic) = newiTempOperand(p,1);
2159 IC_RESULT(ic)->isaddr = 0;
2161 return IC_RESULT(ic);
2163 /*-----------------------------------------------------------------*/
2164 /* setOClass - sets the output class depending on the pointer type */
2165 /*-----------------------------------------------------------------*/
2166 void setOClass (sym_link *ptr, sym_link *spec)
2168 switch (DCL_TYPE(ptr)) {
2170 SPEC_OCLS(spec) = data ;
2174 SPEC_OCLS(spec) = generic;
2178 SPEC_OCLS(spec) = xdata ;
2182 SPEC_OCLS(spec) = code ;
2186 SPEC_OCLS(spec) = idata;
2190 SPEC_OCLS(spec) = xstack;
2194 SPEC_OCLS(spec) = eeprom;
2203 /*-----------------------------------------------------------------*/
2204 /* geniCodeDerefPtr - dereference pointer with '*' */
2205 /*-----------------------------------------------------------------*/
2206 operand *geniCodeDerefPtr (operand *op)
2208 sym_link *rtype , *retype ;
2209 sym_link *optype = operandType(op);
2211 /* if this is a pointer then generate the rvalue */
2212 if (IS_PTR(optype)) {
2213 if (IS_TRUE_SYMOP(op)) {
2215 op = geniCodeRValue(op,TRUE);
2218 op = geniCodeRValue(op,TRUE);
2221 /* now get rid of the pointer part */
2222 if (lvaluereq && IS_ITEMP(op) )
2224 retype = getSpec(rtype = copyLinkChain(optype)) ;
2228 retype = getSpec(rtype = copyLinkChain(optype->next)) ;
2231 /* if this is a pointer then outputclass needs 2b updated */
2233 setOClass(optype,retype);
2235 op->isGptr = IS_GENPTR(optype);
2237 /* if the pointer was declared as a constant */
2238 /* then we cannot allow assignment to the derefed */
2239 if (IS_PTR_CONST(optype))
2240 SPEC_CONST(retype) = 1;
2242 op->isaddr = (IS_PTR(rtype) ||
2249 op = geniCodeRValue(op,TRUE);
2251 setOperandType(op,rtype);
2256 /*-----------------------------------------------------------------*/
2257 /* geniCodeUnaryMinus - does a unary minus of the operand */
2258 /*-----------------------------------------------------------------*/
2259 operand *geniCodeUnaryMinus (operand *op)
2262 sym_link *optype = operandType(op);
2264 if (IS_LITERAL(optype))
2265 return operandFromLit(- floatFromVal(op->operand.valOperand));
2267 ic = newiCode(UNARYMINUS,op,NULL);
2268 IC_RESULT(ic) = newiTempOperand(optype,0);
2270 return IC_RESULT(ic);
2273 /*-----------------------------------------------------------------*/
2274 /* geniCodeLeftShift - gen i code for left shift */
2275 /*-----------------------------------------------------------------*/
2276 operand *geniCodeLeftShift (operand *left, operand *right)
2280 /* Operands must be promoted to int, according to ISO. */
2281 if (getSize(operandType(right)) < INTSIZE)
2283 right = geniCodeCast(INTTYPE,right,TRUE);
2286 /* Note that we don't use the usual binary conversions for the
2287 * shift operations, in accordance with our ANSI friends.
2289 if (options.ANSIint)
2291 right = usualUnaryConversions(right);
2292 left = usualUnaryConversions(left);
2295 ic = newiCode(LEFT_OP,left,right);
2296 IC_RESULT(ic) = newiTempOperand(operandType(left),0);
2298 return IC_RESULT(ic) ;
2301 /*-----------------------------------------------------------------*/
2302 /* geniCodeRightShift - gen i code for right shift */
2303 /*-----------------------------------------------------------------*/
2304 operand *geniCodeRightShift (operand *left, operand *right)
2308 /* Operands must be promoted to int, according to ISO. */
2309 if (getSize(operandType(right)) < INTSIZE)
2311 right = geniCodeCast(INTTYPE,right,TRUE);
2314 /* Note that we don't use the usual binary conversions for the
2315 * shift operations, in accordance with our ANSI friends.
2317 if (options.ANSIint)
2319 right = usualUnaryConversions(right);
2320 left = usualUnaryConversions(left);
2323 ic = newiCode(RIGHT_OP,left,right);
2324 IC_RESULT(ic) = newiTempOperand(operandType(left),0);
2326 return IC_RESULT(ic) ;
2329 #if defined(__BORLANDC__) || defined(_MSC_VER)
2330 #define LONG_LONG __int64
2332 #define LONG_LONG long long
2335 /*-----------------------------------------------------------------*/
2336 /* geniCodeLogic- logic code */
2337 /*-----------------------------------------------------------------*/
2338 operand *geniCodeLogic (operand *left, operand *right, int op )
2342 sym_link *rtype = operandType(right);
2343 sym_link *ltype = operandType(left);
2345 /* left is integral type and right is literal then
2346 check if the literal value is within bounds */
2347 if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2348 int nbits = bitsForType(ltype);
2349 long v = operandLitValue(right);
2351 if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2352 werror(W_CONST_RANGE," compare operation ");
2355 ctype = usualBinaryConversions(&left, &right);
2357 ic = newiCode(op,left,right);
2358 IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2360 /* if comparing anything greater than one byte
2361 and not a '==' || '!=' || '&&' || '||' (these
2363 if (getSize(ctype) > 1 &&
2371 return IC_RESULT(ic);
2374 /*-----------------------------------------------------------------*/
2375 /* geniCodeUnary - for a a generic unary operation */
2376 /*-----------------------------------------------------------------*/
2377 operand *geniCodeUnary (operand *op, int oper )
2379 iCode *ic = newiCode (oper,op,NULL);
2381 IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2383 return IC_RESULT(ic) ;
2386 /*-----------------------------------------------------------------*/
2387 /* geniCodeConditional - geniCode for '?' ':' operation */
2388 /*-----------------------------------------------------------------*/
2389 operand *geniCodeConditional (ast *tree)
2392 symbol *falseLabel = newiTempLabel(NULL);
2393 symbol *exitLabel = newiTempLabel(NULL);
2394 operand *cond = ast2iCode(tree->left);
2395 operand *true, *false , *result;
2397 ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2401 true = ast2iCode(tree->right->left);
2403 /* move the value to a new Operand */
2404 result = newiTempOperand(operandType(true),0);
2405 geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2407 /* generate an unconditional goto */
2408 geniCodeGoto(exitLabel);
2410 /* now for the right side */
2411 geniCodeLabel(falseLabel);
2413 false = ast2iCode(tree->right->right);
2414 geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2416 /* create the exit label */
2417 geniCodeLabel(exitLabel);
2422 /*-----------------------------------------------------------------*/
2423 /* geniCodeAssign - generate code for assignment */
2424 /*-----------------------------------------------------------------*/
2425 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2428 sym_link *ltype = operandType(left);
2429 sym_link *rtype = operandType(right);
2431 if (!left->isaddr && !IS_ITEMP(left)) {
2432 werror(E_LVALUE_REQUIRED,"assignment");
2436 /* left is integral type and right is literal then
2437 check if the literal value is within bounds */
2438 if (IS_INTEGRAL(ltype) && right->type == VALUE && IS_LITERAL(rtype)) {
2439 int nbits = bitsForType(ltype);
2440 long v = operandLitValue(right);
2442 if (v > ((LONG_LONG)1 << nbits) && v > 0)
2443 werror(W_CONST_RANGE," = operation");
2446 /* if the left & right type don't exactly match */
2447 /* if pointer set then make sure the check is
2448 done with the type & not the pointer */
2449 /* then cast rights type to left */
2451 /* first check the type for pointer assignement */
2452 if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2453 checkType(ltype,rtype)<0) {
2454 if (checkType(ltype->next,rtype) < 0)
2455 right = geniCodeCast(ltype->next,right,TRUE);
2457 if (checkType(ltype,rtype) < 0 )
2458 right = geniCodeCast(ltype,right,TRUE);
2460 /* if left is a true symbol & ! volatile
2461 create an assignment to temporary for
2462 the right & then assign this temporary
2463 to the symbol this is SSA . isn't it simple
2464 and folks have published mountains of paper on it */
2465 if (IS_TRUE_SYMOP(left) &&
2466 !isOperandVolatile(left,FALSE) &&
2467 isOperandGlobal(left)) {
2470 if (IS_TRUE_SYMOP(right))
2471 sym = OP_SYMBOL(right);
2472 ic = newiCode('=',NULL,right);
2473 IC_RESULT(ic) = right = newiTempOperand(ltype,0);
2474 SPIL_LOC(right) = sym ;
2478 ic = newiCode('=',NULL,right);
2479 IC_RESULT(ic) = left;
2482 /* if left isgptr flag is set then support
2483 routine will be required */
2487 ic->nosupdate = nosupdate;
2491 /*-----------------------------------------------------------------*/
2492 /* geniCodeSEParms - generate code for side effecting fcalls */
2493 /*-----------------------------------------------------------------*/
2494 static void geniCodeSEParms (ast *parms)
2499 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2500 geniCodeSEParms (parms->left) ;
2501 geniCodeSEParms (parms->right);
2505 /* hack don't like this but too lazy to think of
2507 if (IS_ADDRESS_OF_OP(parms))
2508 parms->left->lvalue = 1;
2510 if (IS_CAST_OP(parms) &&
2511 IS_PTR(parms->ftype) &&
2512 IS_ADDRESS_OF_OP(parms->right))
2513 parms->right->left->lvalue = 1;
2515 parms->opval.oprnd =
2516 geniCodeRValue(ast2iCode (parms),FALSE);
2518 parms->type = EX_OPERAND ;
2521 /*-----------------------------------------------------------------*/
2522 /* geniCodeParms - generates parameters */
2523 /*-----------------------------------------------------------------*/
2524 static void geniCodeParms ( ast *parms , int *stack, sym_link *fetype, symbol *func)
2532 /* if this is a param node then do the left & right */
2533 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2534 geniCodeParms (parms->left, stack,fetype,func) ;
2535 geniCodeParms (parms->right, stack,fetype,func);
2539 /* get the parameter value */
2540 if (parms->type == EX_OPERAND)
2541 pval = parms->opval.oprnd ;
2543 /* maybe this else should go away ?? */
2544 /* hack don't like this but too lazy to think of
2546 if (IS_ADDRESS_OF_OP(parms))
2547 parms->left->lvalue = 1;
2549 if (IS_CAST_OP(parms) &&
2550 IS_PTR(parms->ftype) &&
2551 IS_ADDRESS_OF_OP(parms->right))
2552 parms->right->left->lvalue = 1;
2554 pval = geniCodeRValue(ast2iCode (parms),FALSE);
2557 /* if register parm then make it a send */
2558 if (((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2559 IS_REGPARM(parms->etype)) && !func->hasVargs ) {
2560 ic = newiCode(SEND,pval,NULL);
2563 /* now decide whether to push or assign */
2564 if (!(options.stackAuto || IS_RENT(fetype))) {
2567 operand *top = operandFromSymbol(parms->argSym);
2568 geniCodeAssign(top,pval,1);
2571 sym_link *p = operandType(pval);
2573 ic = newiCode(IPUSH,pval,NULL);
2575 /* update the stack adjustment */
2576 *stack += getSize(IS_AGGREGATE(p)? aggrToPtr(p,FALSE):p);
2583 /*-----------------------------------------------------------------*/
2584 /* geniCodeCall - generates temp code for calling */
2585 /*-----------------------------------------------------------------*/
2586 operand *geniCodeCall (operand *left, ast *parms)
2590 sym_link *type, *etype;
2593 /* take care of parameters with side-effecting
2594 function calls in them, this is required to take care
2595 of overlaying function parameters */
2596 geniCodeSEParms ( parms );
2598 /* first the parameters */
2599 geniCodeParms ( parms , &stack , getSpec(operandType(left)), OP_SYMBOL(left));
2601 /* now call : if symbol then pcall */
2603 ic = newiCode(PCALL,left,NULL);
2605 ic = newiCode(CALL,left,NULL);
2607 IC_ARGS(ic) = left->operand.symOperand->args ;
2608 type = copyLinkChain(operandType(left)->next);
2609 etype = getSpec(type);
2610 SPEC_EXTR(etype) = 0;
2611 IC_RESULT(ic) = result = newiTempOperand(type,1);
2615 /* stack adjustment after call */
2616 left->parmBytes = stack;
2621 /*-----------------------------------------------------------------*/
2622 /* geniCodeReceive - generate intermediate code for "receive" */
2623 /*-----------------------------------------------------------------*/
2624 static void geniCodeReceive (value *args)
2626 /* for all arguments that are passed in registers */
2629 if (IS_REGPARM(args->etype)) {
2630 operand *opr = operandFromValue(args);
2632 symbol *sym = OP_SYMBOL(opr);
2635 /* we will use it after all optimizations
2636 and before liveRange calculation */
2637 if (!sym->addrtaken && !IS_VOLATILE(sym->etype)) {
2639 if (IN_FARSPACE(SPEC_OCLS(sym->etype)) &&
2640 options.stackAuto == 0 &&
2643 opl = newiTempOperand(args->type,0);
2645 sym->reqv->key = sym->key ;
2646 OP_SYMBOL(sym->reqv)->key = sym->key;
2647 OP_SYMBOL(sym->reqv)->isreqv = 1;
2648 OP_SYMBOL(sym->reqv)->islocal= 0;
2649 SPIL_LOC(sym->reqv) = sym;
2653 ic = newiCode(RECEIVE,NULL,NULL);
2654 currFunc->recvSize = getSize(sym->etype);
2655 IC_RESULT(ic) = opr;
2663 /*-----------------------------------------------------------------*/
2664 /* geniCodeFunctionBody - create the function body */
2665 /*-----------------------------------------------------------------*/
2666 void geniCodeFunctionBody (ast *tree)
2673 /* reset the auto generation */
2679 func = ast2iCode(tree->left);
2680 fetype = getSpec(operandType(func));
2682 savelineno = lineno;
2683 lineno = OP_SYMBOL(func)->lineDef;
2684 /* create an entry label */
2685 geniCodeLabel(entryLabel);
2686 lineno = savelineno;
2688 /* create a proc icode */
2689 ic = newiCode(FUNCTION,func,NULL);
2690 /* if the function has parmas then */
2691 /* save the parameters information */
2692 ic->argLabel.args = tree->values.args ;
2693 ic->lineno = OP_SYMBOL(func)->lineDef;
2697 /* for all parameters that are passed
2698 on registers add a "receive" */
2699 geniCodeReceive( tree->values.args );
2701 /* generate code for the body */
2702 ast2iCode(tree->right);
2704 /* create a label for return */
2705 geniCodeLabel(returnLabel);
2707 /* now generate the end proc */
2708 ic = newiCode(ENDFUNCTION,func,NULL);
2713 /*-----------------------------------------------------------------*/
2714 /* geniCodeReturn - gen icode for 'return' statement */
2715 /*-----------------------------------------------------------------*/
2716 void geniCodeReturn (operand *op)
2720 /* if the operand is present force an rvalue */
2722 op = geniCodeRValue(op,FALSE);
2724 ic = newiCode(RETURN,op,NULL);
2728 /*-----------------------------------------------------------------*/
2729 /* geniCodeIfx - generates code for extended if statement */
2730 /*-----------------------------------------------------------------*/
2731 void geniCodeIfx (ast *tree)
2734 operand *condition = ast2iCode(tree->left);
2737 /* if condition is null then exit */
2741 condition = geniCodeRValue(condition,FALSE);
2743 cetype = getSpec(operandType(condition));
2744 /* if the condition is a literal */
2745 if (IS_LITERAL(cetype)) {
2746 if (floatFromVal(condition->operand.valOperand)) {
2747 if (tree->trueLabel)
2748 geniCodeGoto(tree->trueLabel);
2753 if (tree->falseLabel)
2754 geniCodeGoto (tree->falseLabel);
2761 if ( tree->trueLabel ) {
2762 ic = newiCodeCondition(condition,
2767 if ( tree->falseLabel)
2768 geniCodeGoto(tree->falseLabel);
2771 ic = newiCodeCondition (condition,
2778 ast2iCode(tree->right);
2781 /*-----------------------------------------------------------------*/
2782 /* geniCodeJumpTable - tries to create a jump table for switch */
2783 /*-----------------------------------------------------------------*/
2784 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2786 int min = 0 ,max = 0, t, cnt = 0;
2791 set *labels = NULL ;
2793 if (!tree || !caseVals)
2796 /* the criteria for creating a jump table is */
2797 /* all integer numbers between the maximum & minimum must */
2798 /* be present , the maximum value should not exceed 255 */
2799 min = max = (int)floatFromVal(vch = caseVals);
2800 sprintf(buffer,"_case_%d_%d",
2801 tree->values.switchVals.swNum,
2803 addSet(&labels,newiTempLabel(buffer));
2805 /* if there is only one case value then no need */
2806 if (!(vch = vch->next ))
2810 if (((t = (int)floatFromVal(vch)) - max) != 1)
2812 sprintf(buffer,"_case_%d_%d",
2813 tree->values.switchVals.swNum,
2815 addSet(&labels,newiTempLabel(buffer));
2821 /* if the number of case statements <= 2 then */
2822 /* it is not economical to create the jump table */
2823 /* since two compares are needed for boundary conditions */
2824 if ((! optimize.noJTabBoundary && cnt <= 2) || max > (255/3))
2827 if ( tree->values.switchVals.swDefault )
2828 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2830 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2832 falseLabel = newiTempLabel (buffer);
2834 /* so we can create a jumptable */
2835 /* first we rule out the boundary conditions */
2836 /* if only optimization says so */
2837 if ( ! optimize.noJTabBoundary ) {
2838 sym_link *cetype = getSpec(operandType(cond));
2839 /* no need to check the lower bound if
2840 the condition is unsigned & minimum value is zero */
2841 if (!( min == 0 && SPEC_USIGN(cetype))) {
2842 boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2843 ic = newiCodeCondition (boundary,falseLabel,NULL);
2847 /* now for upper bounds */
2848 boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2849 ic = newiCodeCondition (boundary,falseLabel,NULL);
2853 /* if the min is not zero then we no make it zero */
2855 cond = geniCodeSubtract(cond,operandFromLit(min));
2856 setOperandType(cond, UCHARTYPE);
2859 /* now create the jumptable */
2860 ic = newiCode(JUMPTABLE,NULL,NULL);
2861 IC_JTCOND(ic) = cond;
2862 IC_JTLABELS(ic) = labels;
2867 /*-----------------------------------------------------------------*/
2868 /* geniCodeSwitch - changes a switch to a if statement */
2869 /*-----------------------------------------------------------------*/
2870 void geniCodeSwitch (ast *tree)
2873 operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2874 value *caseVals = tree->values.switchVals.swVals ;
2875 symbol *trueLabel , *falseLabel;
2877 /* if we can make this a jump table */
2878 if ( geniCodeJumpTable (cond,caseVals,tree) )
2879 goto jumpTable ; /* no need for the comparison */
2881 /* for the cases defined do */
2884 operand *compare = geniCodeLogic (cond,
2885 operandFromValue(caseVals),
2888 sprintf(buffer,"_case_%d_%d",
2889 tree->values.switchVals.swNum,
2890 (int) floatFromVal(caseVals));
2891 trueLabel = newiTempLabel(buffer);
2893 ic = newiCodeCondition(compare,trueLabel,NULL);
2895 caseVals = caseVals->next;
2900 /* if default is present then goto break else break */
2901 if ( tree->values.switchVals.swDefault )
2902 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2904 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2906 falseLabel = newiTempLabel (buffer);
2907 geniCodeGoto(falseLabel);
2910 ast2iCode(tree->right);
2913 /*-----------------------------------------------------------------*/
2914 /* geniCodeInline - intermediate code for inline assembler */
2915 /*-----------------------------------------------------------------*/
2916 static void geniCodeInline (ast *tree)
2920 ic = newiCode(INLINEASM,NULL,NULL);
2921 IC_INLINE(ic) = tree->values.inlineasm;
2925 /*-----------------------------------------------------------------*/
2926 /* ast2iCode - creates an icodeList from an ast */
2927 /*-----------------------------------------------------------------*/
2928 operand *ast2iCode (ast *tree)
2930 operand *left = NULL;
2931 operand *right= NULL;
2936 /* set the global variables for filename & line number */
2937 if ( tree->filename )
2938 filename = tree->filename ;
2940 lineno = tree->lineno ;
2942 block = tree->block ;
2944 scopeLevel = tree->level;
2946 if (tree->type == EX_VALUE )
2947 return operandFromValue(tree->opval.val);
2949 if (tree->type == EX_LINK )
2950 return operandFromLink (tree->opval.lnk);
2952 /* if we find a nullop */
2953 if (tree->type == EX_OP &&
2954 ( tree->opval.op == NULLOP ||
2955 tree->opval.op == BLOCK )) {
2956 ast2iCode (tree->left);
2957 ast2iCode (tree->right);
2961 /* special cases for not evaluating */
2962 if ( tree->opval.op != ':' &&
2963 tree->opval.op != '?' &&
2964 tree->opval.op != CALL &&
2965 tree->opval.op != IFX &&
2966 tree->opval.op != LABEL &&
2967 tree->opval.op != GOTO &&
2968 tree->opval.op != SWITCH &&
2969 tree->opval.op != FUNCTION &&
2970 tree->opval.op != INLINEASM ) {
2972 if (IS_ASSIGN_OP(tree->opval.op) ||
2973 IS_DEREF_OP(tree) ||
2974 (tree->opval.op == '&' && !tree->right) ||
2975 tree->opval.op == PTR_OP) {
2977 if ((IS_ARRAY_OP(tree->left) && IS_ARRAY_OP(tree->left->left)) ||
2978 (IS_DEREF_OP(tree) && IS_ARRAY_OP(tree->left)))
2980 int olvr = lvaluereq ;
2982 left = operandFromAst(tree->left);
2983 lvaluereq = olvr - 1;
2985 left = operandFromAst(tree->left);
2988 if (IS_DEREF_OP(tree) && IS_DEREF_OP(tree->left))
2989 left = geniCodeRValue(left,TRUE);
2991 left = operandFromAst(tree->left);
2993 if (tree->opval.op == INC_OP ||
2994 tree->opval.op == DEC_OP) {
2996 right= operandFromAst(tree->right);
2999 right= operandFromAst(tree->right);
3003 /* now depending on the type of operand */
3004 /* this will be a biggy */
3005 switch (tree->opval.op) {
3007 case '[' : /* array operation */
3009 sym_link *ltype = operandType(left);
3010 left= geniCodeRValue (left,IS_PTR(ltype->next) ? TRUE : FALSE);
3011 right=geniCodeRValue (right,TRUE);
3014 return geniCodeArray (left,right);
3016 case '.' : /* structure dereference */
3017 if (IS_PTR(operandType(left)))
3018 left = geniCodeRValue(left,TRUE);
3020 left = geniCodeRValue(left,FALSE);
3022 return geniCodeStruct (left,right,tree->lvalue);
3024 case PTR_OP: /* structure pointer dereference */
3027 pType = operandType(left);
3028 left = geniCodeRValue(left,TRUE);
3030 setOClass (pType,getSpec(operandType(left)));
3033 return geniCodeStruct (left, right,tree->lvalue);
3035 case INC_OP: /* increment operator */
3037 return geniCodePostInc (left);
3039 return geniCodePreInc (right);
3041 case DEC_OP: /* decrement operator */
3043 return geniCodePostDec (left);
3045 return geniCodePreDec (right);
3047 case '&' : /* bitwise and or address of operator */
3048 if ( right ) { /* this is a bitwise operator */
3049 left= geniCodeRValue(left,FALSE);
3050 right= geniCodeRValue(right,FALSE);
3051 return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
3053 return geniCodeAddressOf (left);
3055 case '|': /* bitwise or & xor */
3057 return geniCodeBitwise (geniCodeRValue(left,FALSE),
3058 geniCodeRValue(right,FALSE),
3063 return geniCodeDivision (geniCodeRValue(left,FALSE),
3064 geniCodeRValue(right,FALSE));
3067 return geniCodeModulus (geniCodeRValue(left,FALSE),
3068 geniCodeRValue(right,FALSE));
3071 return geniCodeMultiply (geniCodeRValue(left,FALSE),
3072 geniCodeRValue(right,FALSE),FALSE);
3074 return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
3078 return geniCodeSubtract (geniCodeRValue(left,FALSE),
3079 geniCodeRValue(right,FALSE));
3081 return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
3085 return geniCodeAdd (geniCodeRValue(left,FALSE),
3086 geniCodeRValue(right,FALSE));
3088 return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
3091 return geniCodeLeftShift (geniCodeRValue(left,FALSE),
3092 geniCodeRValue(right,FALSE));
3095 return geniCodeRightShift (geniCodeRValue(left,FALSE),
3096 geniCodeRValue(right,FALSE));
3098 return geniCodeCast (operandType(left),
3099 geniCodeRValue(right,FALSE),FALSE);
3105 return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
3109 operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
3110 setOperandType(op, UCHARTYPE);
3121 return geniCodeLogic (geniCodeRValue(left,FALSE),
3122 geniCodeRValue(right,FALSE),
3125 return geniCodeConditional (tree);
3128 return operandFromLit(getSize(tree->right->ftype));
3132 sym_link *rtype = operandType(right);
3133 sym_link *ltype = operandType(left);
3134 if (IS_PTR(rtype) && IS_ITEMP(right)
3135 && right->isaddr && checkType(rtype->next,ltype)==1)
3136 right = geniCodeRValue(right,TRUE);
3138 right = geniCodeRValue(right,FALSE);
3140 geniCodeAssign (left,right,0);
3145 geniCodeAssign(left,
3146 geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
3148 geniCodeRValue(right,FALSE),FALSE),0);
3152 geniCodeAssign(left,
3153 geniCodeDivision(geniCodeRValue(operandFromOperand(left),
3155 geniCodeRValue(right,FALSE)),0);
3158 geniCodeAssign(left,
3159 geniCodeModulus(geniCodeRValue(operandFromOperand(left),
3161 geniCodeRValue(right,FALSE)),0);
3164 sym_link *rtype = operandType(right);
3165 sym_link *ltype = operandType(left);
3166 if (IS_PTR(rtype) && IS_ITEMP(right)
3167 && right->isaddr && checkType(rtype->next,ltype)==1)
3168 right = geniCodeRValue(right,TRUE);
3170 right = geniCodeRValue(right,FALSE);
3173 return geniCodeAssign(left,
3174 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
3180 sym_link *rtype = operandType(right);
3181 sym_link *ltype = operandType(left);
3182 if (IS_PTR(rtype) && IS_ITEMP(right)
3183 && right->isaddr && checkType(rtype->next,ltype)==1) {
3184 right = geniCodeRValue(right,TRUE);
3187 right = geniCodeRValue(right,FALSE);
3190 geniCodeAssign (left,
3191 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
3197 geniCodeAssign (left,
3198 geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
3200 geniCodeRValue(right,FALSE)),0);
3203 geniCodeAssign(left,
3204 geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
3206 geniCodeRValue(right,FALSE)),0);
3209 geniCodeAssign (left,
3210 geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
3212 geniCodeRValue(right,FALSE),
3214 operandType(left)),0);
3217 geniCodeAssign (left,
3218 geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3220 geniCodeRValue(right,FALSE),
3222 operandType(left)),0);
3225 geniCodeAssign (left,
3226 geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3228 geniCodeRValue(right,FALSE),
3230 operandType(left)),0);
3232 return geniCodeRValue(right,FALSE);
3235 return geniCodeCall (ast2iCode(tree->left),
3238 geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3239 return ast2iCode (tree->right);
3242 geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3243 return ast2iCode (tree->right);
3246 geniCodeFunctionBody ( tree );
3250 geniCodeReturn (right);
3258 geniCodeSwitch (tree);
3262 geniCodeInline (tree);
3269 /*-----------------------------------------------------------------*/
3270 /* reverseICChain - gets from the list and creates a linkedlist */
3271 /*-----------------------------------------------------------------*/
3272 iCode *reverseiCChain ()
3274 iCode *loop = NULL ;
3275 iCode *prev = NULL ;
3277 while ((loop = getSet(&iCodeChain))) {
3288 /*-----------------------------------------------------------------*/
3289 /* iCodeFromAst - given an ast will convert it to iCode */
3290 /*-----------------------------------------------------------------*/
3291 iCode *iCodeFromAst ( ast *tree )
3293 returnLabel = newiTempLabel("_return");
3294 entryLabel = newiTempLabel("_entry") ;
3296 return reverseiCChain ();