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)
2281 /* Note that we don't use the usual binary conversions for the
2282 * shift operations, in accordance with our ANSI friends.
2284 if (options.ANSIint)
2286 right = usualUnaryConversions(right);
2287 left = usualUnaryConversions(left);
2290 ic = newiCode(LEFT_OP,left,right);
2291 IC_RESULT(ic) = newiTempOperand(operandType(left),0);
2293 return IC_RESULT(ic) ;
2296 /*-----------------------------------------------------------------*/
2297 /* geniCodeRightShift - gen i code for right shift */
2298 /*-----------------------------------------------------------------*/
2299 operand *geniCodeRightShift (operand *left, operand *right)
2304 /* Note that we don't use the usual binary conversions for the
2305 * shift operations, in accordance with our ANSI friends.
2307 if (options.ANSIint)
2309 right = usualUnaryConversions(right);
2310 left = usualUnaryConversions(left);
2313 ic = newiCode(RIGHT_OP,left,right);
2314 IC_RESULT(ic) = newiTempOperand(operandType(left),0);
2316 return IC_RESULT(ic) ;
2319 #if defined(__BORLANDC__) || defined(_MSC_VER)
2320 #define LONG_LONG __int64
2322 #define LONG_LONG long long
2325 /*-----------------------------------------------------------------*/
2326 /* geniCodeLogic- logic code */
2327 /*-----------------------------------------------------------------*/
2328 operand *geniCodeLogic (operand *left, operand *right, int op )
2332 sym_link *rtype = operandType(right);
2333 sym_link *ltype = operandType(left);
2335 /* left is integral type and right is literal then
2336 check if the literal value is within bounds */
2337 if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2338 int nbits = bitsForType(ltype);
2339 long v = operandLitValue(right);
2341 if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2342 werror(W_CONST_RANGE," compare operation ");
2345 ctype = usualBinaryConversions(&left, &right);
2347 ic = newiCode(op,left,right);
2348 IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2350 /* if comparing anything greater than one byte
2351 and not a '==' || '!=' || '&&' || '||' (these
2353 if (getSize(ctype) > 1 &&
2361 return IC_RESULT(ic);
2364 /*-----------------------------------------------------------------*/
2365 /* geniCodeUnary - for a a generic unary operation */
2366 /*-----------------------------------------------------------------*/
2367 operand *geniCodeUnary (operand *op, int oper )
2369 iCode *ic = newiCode (oper,op,NULL);
2371 IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2373 return IC_RESULT(ic) ;
2376 /*-----------------------------------------------------------------*/
2377 /* geniCodeConditional - geniCode for '?' ':' operation */
2378 /*-----------------------------------------------------------------*/
2379 operand *geniCodeConditional (ast *tree)
2382 symbol *falseLabel = newiTempLabel(NULL);
2383 symbol *exitLabel = newiTempLabel(NULL);
2384 operand *cond = ast2iCode(tree->left);
2385 operand *true, *false , *result;
2387 ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2391 true = ast2iCode(tree->right->left);
2393 /* move the value to a new Operand */
2394 result = newiTempOperand(operandType(true),0);
2395 geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2397 /* generate an unconditional goto */
2398 geniCodeGoto(exitLabel);
2400 /* now for the right side */
2401 geniCodeLabel(falseLabel);
2403 false = ast2iCode(tree->right->right);
2404 geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2406 /* create the exit label */
2407 geniCodeLabel(exitLabel);
2412 /*-----------------------------------------------------------------*/
2413 /* geniCodeAssign - generate code for assignment */
2414 /*-----------------------------------------------------------------*/
2415 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2418 sym_link *ltype = operandType(left);
2419 sym_link *rtype = operandType(right);
2421 if (!left->isaddr && !IS_ITEMP(left)) {
2422 werror(E_LVALUE_REQUIRED,"assignment");
2426 /* left is integral type and right is literal then
2427 check if the literal value is within bounds */
2428 if (IS_INTEGRAL(ltype) && right->type == VALUE && IS_LITERAL(rtype)) {
2429 int nbits = bitsForType(ltype);
2430 long v = operandLitValue(right);
2432 if (v > ((LONG_LONG)1 << nbits) && v > 0)
2433 werror(W_CONST_RANGE," = operation");
2436 /* if the left & right type don't exactly match */
2437 /* if pointer set then make sure the check is
2438 done with the type & not the pointer */
2439 /* then cast rights type to left */
2441 /* first check the type for pointer assignement */
2442 if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2443 checkType(ltype,rtype)<0) {
2444 if (checkType(ltype->next,rtype) < 0)
2445 right = geniCodeCast(ltype->next,right,TRUE);
2447 if (checkType(ltype,rtype) < 0 )
2448 right = geniCodeCast(ltype,right,TRUE);
2450 /* if left is a true symbol & ! volatile
2451 create an assignment to temporary for
2452 the right & then assign this temporary
2453 to the symbol this is SSA . isn't it simple
2454 and folks have published mountains of paper on it */
2455 if (IS_TRUE_SYMOP(left) &&
2456 !isOperandVolatile(left,FALSE) &&
2457 isOperandGlobal(left)) {
2460 if (IS_TRUE_SYMOP(right))
2461 sym = OP_SYMBOL(right);
2462 ic = newiCode('=',NULL,right);
2463 IC_RESULT(ic) = right = newiTempOperand(ltype,0);
2464 SPIL_LOC(right) = sym ;
2468 ic = newiCode('=',NULL,right);
2469 IC_RESULT(ic) = left;
2472 /* if left isgptr flag is set then support
2473 routine will be required */
2477 ic->nosupdate = nosupdate;
2481 /*-----------------------------------------------------------------*/
2482 /* geniCodeSEParms - generate code for side effecting fcalls */
2483 /*-----------------------------------------------------------------*/
2484 static void geniCodeSEParms (ast *parms)
2489 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2490 geniCodeSEParms (parms->left) ;
2491 geniCodeSEParms (parms->right);
2495 /* hack don't like this but too lazy to think of
2497 if (IS_ADDRESS_OF_OP(parms))
2498 parms->left->lvalue = 1;
2500 if (IS_CAST_OP(parms) &&
2501 IS_PTR(parms->ftype) &&
2502 IS_ADDRESS_OF_OP(parms->right))
2503 parms->right->left->lvalue = 1;
2505 parms->opval.oprnd =
2506 geniCodeRValue(ast2iCode (parms),FALSE);
2508 parms->type = EX_OPERAND ;
2511 /*-----------------------------------------------------------------*/
2512 /* geniCodeParms - generates parameters */
2513 /*-----------------------------------------------------------------*/
2514 static void geniCodeParms ( ast *parms , int *stack, sym_link *fetype, symbol *func)
2522 /* if this is a param node then do the left & right */
2523 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2524 geniCodeParms (parms->left, stack,fetype,func) ;
2525 geniCodeParms (parms->right, stack,fetype,func);
2529 /* get the parameter value */
2530 if (parms->type == EX_OPERAND)
2531 pval = parms->opval.oprnd ;
2533 /* maybe this else should go away ?? */
2534 /* hack don't like this but too lazy to think of
2536 if (IS_ADDRESS_OF_OP(parms))
2537 parms->left->lvalue = 1;
2539 if (IS_CAST_OP(parms) &&
2540 IS_PTR(parms->ftype) &&
2541 IS_ADDRESS_OF_OP(parms->right))
2542 parms->right->left->lvalue = 1;
2544 pval = geniCodeRValue(ast2iCode (parms),FALSE);
2547 /* if register parm then make it a send */
2548 if (((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2549 IS_REGPARM(parms->etype)) && !func->hasVargs ) {
2550 ic = newiCode(SEND,pval,NULL);
2553 /* now decide whether to push or assign */
2554 if (!(options.stackAuto || IS_RENT(fetype))) {
2557 operand *top = operandFromSymbol(parms->argSym);
2558 geniCodeAssign(top,pval,1);
2561 sym_link *p = operandType(pval);
2563 ic = newiCode(IPUSH,pval,NULL);
2565 /* update the stack adjustment */
2566 *stack += getSize(IS_AGGREGATE(p)? aggrToPtr(p,FALSE):p);
2573 /*-----------------------------------------------------------------*/
2574 /* geniCodeCall - generates temp code for calling */
2575 /*-----------------------------------------------------------------*/
2576 operand *geniCodeCall (operand *left, ast *parms)
2580 sym_link *type, *etype;
2583 /* take care of parameters with side-effecting
2584 function calls in them, this is required to take care
2585 of overlaying function parameters */
2586 geniCodeSEParms ( parms );
2588 /* first the parameters */
2589 geniCodeParms ( parms , &stack , getSpec(operandType(left)), OP_SYMBOL(left));
2591 /* now call : if symbol then pcall */
2593 ic = newiCode(PCALL,left,NULL);
2595 ic = newiCode(CALL,left,NULL);
2597 IC_ARGS(ic) = left->operand.symOperand->args ;
2598 type = copyLinkChain(operandType(left)->next);
2599 etype = getSpec(type);
2600 SPEC_EXTR(etype) = 0;
2601 IC_RESULT(ic) = result = newiTempOperand(type,1);
2605 /* stack adjustment after call */
2606 left->parmBytes = stack;
2611 /*-----------------------------------------------------------------*/
2612 /* geniCodeReceive - generate intermediate code for "receive" */
2613 /*-----------------------------------------------------------------*/
2614 static void geniCodeReceive (value *args)
2616 /* for all arguments that are passed in registers */
2619 if (IS_REGPARM(args->etype)) {
2620 operand *opr = operandFromValue(args);
2622 symbol *sym = OP_SYMBOL(opr);
2625 /* we will use it after all optimizations
2626 and before liveRange calculation */
2627 if (!sym->addrtaken && !IS_VOLATILE(sym->etype)) {
2629 if (IN_FARSPACE(SPEC_OCLS(sym->etype)) &&
2630 options.stackAuto == 0 &&
2633 opl = newiTempOperand(args->type,0);
2635 sym->reqv->key = sym->key ;
2636 OP_SYMBOL(sym->reqv)->key = sym->key;
2637 OP_SYMBOL(sym->reqv)->isreqv = 1;
2638 OP_SYMBOL(sym->reqv)->islocal= 0;
2639 SPIL_LOC(sym->reqv) = sym;
2643 ic = newiCode(RECEIVE,NULL,NULL);
2644 currFunc->recvSize = getSize(sym->etype);
2645 IC_RESULT(ic) = opr;
2653 /*-----------------------------------------------------------------*/
2654 /* geniCodeFunctionBody - create the function body */
2655 /*-----------------------------------------------------------------*/
2656 void geniCodeFunctionBody (ast *tree)
2663 /* reset the auto generation */
2669 func = ast2iCode(tree->left);
2670 fetype = getSpec(operandType(func));
2672 savelineno = lineno;
2673 lineno = OP_SYMBOL(func)->lineDef;
2674 /* create an entry label */
2675 geniCodeLabel(entryLabel);
2676 lineno = savelineno;
2678 /* create a proc icode */
2679 ic = newiCode(FUNCTION,func,NULL);
2680 /* if the function has parmas then */
2681 /* save the parameters information */
2682 ic->argLabel.args = tree->values.args ;
2683 ic->lineno = OP_SYMBOL(func)->lineDef;
2687 /* for all parameters that are passed
2688 on registers add a "receive" */
2689 geniCodeReceive( tree->values.args );
2691 /* generate code for the body */
2692 ast2iCode(tree->right);
2694 /* create a label for return */
2695 geniCodeLabel(returnLabel);
2697 /* now generate the end proc */
2698 ic = newiCode(ENDFUNCTION,func,NULL);
2703 /*-----------------------------------------------------------------*/
2704 /* geniCodeReturn - gen icode for 'return' statement */
2705 /*-----------------------------------------------------------------*/
2706 void geniCodeReturn (operand *op)
2710 /* if the operand is present force an rvalue */
2712 op = geniCodeRValue(op,FALSE);
2714 ic = newiCode(RETURN,op,NULL);
2718 /*-----------------------------------------------------------------*/
2719 /* geniCodeIfx - generates code for extended if statement */
2720 /*-----------------------------------------------------------------*/
2721 void geniCodeIfx (ast *tree)
2724 operand *condition = ast2iCode(tree->left);
2727 /* if condition is null then exit */
2731 condition = geniCodeRValue(condition,FALSE);
2733 cetype = getSpec(operandType(condition));
2734 /* if the condition is a literal */
2735 if (IS_LITERAL(cetype)) {
2736 if (floatFromVal(condition->operand.valOperand)) {
2737 if (tree->trueLabel)
2738 geniCodeGoto(tree->trueLabel);
2743 if (tree->falseLabel)
2744 geniCodeGoto (tree->falseLabel);
2751 if ( tree->trueLabel ) {
2752 ic = newiCodeCondition(condition,
2757 if ( tree->falseLabel)
2758 geniCodeGoto(tree->falseLabel);
2761 ic = newiCodeCondition (condition,
2768 ast2iCode(tree->right);
2771 /*-----------------------------------------------------------------*/
2772 /* geniCodeJumpTable - tries to create a jump table for switch */
2773 /*-----------------------------------------------------------------*/
2774 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2776 int min = 0 ,max = 0, t, cnt = 0;
2781 set *labels = NULL ;
2783 if (!tree || !caseVals)
2786 /* the criteria for creating a jump table is */
2787 /* all integer numbers between the maximum & minimum must */
2788 /* be present , the maximum value should not exceed 255 */
2789 min = max = (int)floatFromVal(vch = caseVals);
2790 sprintf(buffer,"_case_%d_%d",
2791 tree->values.switchVals.swNum,
2793 addSet(&labels,newiTempLabel(buffer));
2795 /* if there is only one case value then no need */
2796 if (!(vch = vch->next ))
2800 if (((t = (int)floatFromVal(vch)) - max) != 1)
2802 sprintf(buffer,"_case_%d_%d",
2803 tree->values.switchVals.swNum,
2805 addSet(&labels,newiTempLabel(buffer));
2811 /* if the number of case statements <= 2 then */
2812 /* it is not economical to create the jump table */
2813 /* since two compares are needed for boundary conditions */
2814 if ((! optimize.noJTabBoundary && cnt <= 2) || max > (255/3))
2817 if ( tree->values.switchVals.swDefault )
2818 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2820 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2822 falseLabel = newiTempLabel (buffer);
2824 /* so we can create a jumptable */
2825 /* first we rule out the boundary conditions */
2826 /* if only optimization says so */
2827 if ( ! optimize.noJTabBoundary ) {
2828 sym_link *cetype = getSpec(operandType(cond));
2829 /* no need to check the lower bound if
2830 the condition is unsigned & minimum value is zero */
2831 if (!( min == 0 && SPEC_USIGN(cetype))) {
2832 boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2833 ic = newiCodeCondition (boundary,falseLabel,NULL);
2837 /* now for upper bounds */
2838 boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2839 ic = newiCodeCondition (boundary,falseLabel,NULL);
2843 /* if the min is not zero then we no make it zero */
2845 cond = geniCodeSubtract(cond,operandFromLit(min));
2846 setOperandType(cond, UCHARTYPE);
2849 /* now create the jumptable */
2850 ic = newiCode(JUMPTABLE,NULL,NULL);
2851 IC_JTCOND(ic) = cond;
2852 IC_JTLABELS(ic) = labels;
2857 /*-----------------------------------------------------------------*/
2858 /* geniCodeSwitch - changes a switch to a if statement */
2859 /*-----------------------------------------------------------------*/
2860 void geniCodeSwitch (ast *tree)
2863 operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2864 value *caseVals = tree->values.switchVals.swVals ;
2865 symbol *trueLabel , *falseLabel;
2867 /* if we can make this a jump table */
2868 if ( geniCodeJumpTable (cond,caseVals,tree) )
2869 goto jumpTable ; /* no need for the comparison */
2871 /* for the cases defined do */
2874 operand *compare = geniCodeLogic (cond,
2875 operandFromValue(caseVals),
2878 sprintf(buffer,"_case_%d_%d",
2879 tree->values.switchVals.swNum,
2880 (int) floatFromVal(caseVals));
2881 trueLabel = newiTempLabel(buffer);
2883 ic = newiCodeCondition(compare,trueLabel,NULL);
2885 caseVals = caseVals->next;
2890 /* if default is present then goto break else break */
2891 if ( tree->values.switchVals.swDefault )
2892 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2894 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2896 falseLabel = newiTempLabel (buffer);
2897 geniCodeGoto(falseLabel);
2900 ast2iCode(tree->right);
2903 /*-----------------------------------------------------------------*/
2904 /* geniCodeInline - intermediate code for inline assembler */
2905 /*-----------------------------------------------------------------*/
2906 static void geniCodeInline (ast *tree)
2910 ic = newiCode(INLINEASM,NULL,NULL);
2911 IC_INLINE(ic) = tree->values.inlineasm;
2915 /*-----------------------------------------------------------------*/
2916 /* ast2iCode - creates an icodeList from an ast */
2917 /*-----------------------------------------------------------------*/
2918 operand *ast2iCode (ast *tree)
2920 operand *left = NULL;
2921 operand *right= NULL;
2926 /* set the global variables for filename & line number */
2927 if ( tree->filename )
2928 filename = tree->filename ;
2930 lineno = tree->lineno ;
2932 block = tree->block ;
2934 scopeLevel = tree->level;
2936 if (tree->type == EX_VALUE )
2937 return operandFromValue(tree->opval.val);
2939 if (tree->type == EX_LINK )
2940 return operandFromLink (tree->opval.lnk);
2942 /* if we find a nullop */
2943 if (tree->type == EX_OP &&
2944 ( tree->opval.op == NULLOP ||
2945 tree->opval.op == BLOCK )) {
2946 ast2iCode (tree->left);
2947 ast2iCode (tree->right);
2951 /* special cases for not evaluating */
2952 if ( tree->opval.op != ':' &&
2953 tree->opval.op != '?' &&
2954 tree->opval.op != CALL &&
2955 tree->opval.op != IFX &&
2956 tree->opval.op != LABEL &&
2957 tree->opval.op != GOTO &&
2958 tree->opval.op != SWITCH &&
2959 tree->opval.op != FUNCTION &&
2960 tree->opval.op != INLINEASM ) {
2962 if (IS_ASSIGN_OP(tree->opval.op) ||
2963 IS_DEREF_OP(tree) ||
2964 (tree->opval.op == '&' && !tree->right) ||
2965 tree->opval.op == PTR_OP) {
2967 if ((IS_ARRAY_OP(tree->left) && IS_ARRAY_OP(tree->left->left)) ||
2968 (IS_DEREF_OP(tree) && IS_ARRAY_OP(tree->left)))
2970 int olvr = lvaluereq ;
2972 left = operandFromAst(tree->left);
2973 lvaluereq = olvr - 1;
2975 left = operandFromAst(tree->left);
2978 if (IS_DEREF_OP(tree) && IS_DEREF_OP(tree->left))
2979 left = geniCodeRValue(left,TRUE);
2981 left = operandFromAst(tree->left);
2983 if (tree->opval.op == INC_OP ||
2984 tree->opval.op == DEC_OP) {
2986 right= operandFromAst(tree->right);
2989 right= operandFromAst(tree->right);
2993 /* now depending on the type of operand */
2994 /* this will be a biggy */
2995 switch (tree->opval.op) {
2997 case '[' : /* array operation */
2999 sym_link *ltype = operandType(left);
3000 left= geniCodeRValue (left,IS_PTR(ltype->next) ? TRUE : FALSE);
3001 right=geniCodeRValue (right,TRUE);
3004 return geniCodeArray (left,right);
3006 case '.' : /* structure dereference */
3007 if (IS_PTR(operandType(left)))
3008 left = geniCodeRValue(left,TRUE);
3010 left = geniCodeRValue(left,FALSE);
3012 return geniCodeStruct (left,right,tree->lvalue);
3014 case PTR_OP: /* structure pointer dereference */
3017 pType = operandType(left);
3018 left = geniCodeRValue(left,TRUE);
3020 setOClass (pType,getSpec(operandType(left)));
3023 return geniCodeStruct (left, right,tree->lvalue);
3025 case INC_OP: /* increment operator */
3027 return geniCodePostInc (left);
3029 return geniCodePreInc (right);
3031 case DEC_OP: /* decrement operator */
3033 return geniCodePostDec (left);
3035 return geniCodePreDec (right);
3037 case '&' : /* bitwise and or address of operator */
3038 if ( right ) { /* this is a bitwise operator */
3039 left= geniCodeRValue(left,FALSE);
3040 right= geniCodeRValue(right,FALSE);
3041 return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
3043 return geniCodeAddressOf (left);
3045 case '|': /* bitwise or & xor */
3047 return geniCodeBitwise (geniCodeRValue(left,FALSE),
3048 geniCodeRValue(right,FALSE),
3053 return geniCodeDivision (geniCodeRValue(left,FALSE),
3054 geniCodeRValue(right,FALSE));
3057 return geniCodeModulus (geniCodeRValue(left,FALSE),
3058 geniCodeRValue(right,FALSE));
3061 return geniCodeMultiply (geniCodeRValue(left,FALSE),
3062 geniCodeRValue(right,FALSE),FALSE);
3064 return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
3068 return geniCodeSubtract (geniCodeRValue(left,FALSE),
3069 geniCodeRValue(right,FALSE));
3071 return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
3075 return geniCodeAdd (geniCodeRValue(left,FALSE),
3076 geniCodeRValue(right,FALSE));
3078 return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
3081 return geniCodeLeftShift (geniCodeRValue(left,FALSE),
3082 geniCodeRValue(right,FALSE));
3085 return geniCodeRightShift (geniCodeRValue(left,FALSE),
3086 geniCodeRValue(right,FALSE));
3088 return geniCodeCast (operandType(left),
3089 geniCodeRValue(right,FALSE),FALSE);
3095 return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
3099 operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
3100 setOperandType(op, UCHARTYPE);
3111 return geniCodeLogic (geniCodeRValue(left,FALSE),
3112 geniCodeRValue(right,FALSE),
3115 return geniCodeConditional (tree);
3118 return operandFromLit(getSize(tree->right->ftype));
3122 sym_link *rtype = operandType(right);
3123 sym_link *ltype = operandType(left);
3124 if (IS_PTR(rtype) && IS_ITEMP(right)
3125 && right->isaddr && checkType(rtype->next,ltype)==1)
3126 right = geniCodeRValue(right,TRUE);
3128 right = geniCodeRValue(right,FALSE);
3130 geniCodeAssign (left,right,0);
3135 geniCodeAssign(left,
3136 geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
3138 geniCodeRValue(right,FALSE),FALSE),0);
3142 geniCodeAssign(left,
3143 geniCodeDivision(geniCodeRValue(operandFromOperand(left),
3145 geniCodeRValue(right,FALSE)),0);
3148 geniCodeAssign(left,
3149 geniCodeModulus(geniCodeRValue(operandFromOperand(left),
3151 geniCodeRValue(right,FALSE)),0);
3154 sym_link *rtype = operandType(right);
3155 sym_link *ltype = operandType(left);
3156 if (IS_PTR(rtype) && IS_ITEMP(right)
3157 && right->isaddr && checkType(rtype->next,ltype)==1)
3158 right = geniCodeRValue(right,TRUE);
3160 right = geniCodeRValue(right,FALSE);
3163 return geniCodeAssign(left,
3164 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
3170 sym_link *rtype = operandType(right);
3171 sym_link *ltype = operandType(left);
3172 if (IS_PTR(rtype) && IS_ITEMP(right)
3173 && right->isaddr && checkType(rtype->next,ltype)==1) {
3174 right = geniCodeRValue(right,TRUE);
3177 right = geniCodeRValue(right,FALSE);
3180 geniCodeAssign (left,
3181 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
3187 geniCodeAssign (left,
3188 geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
3190 geniCodeRValue(right,FALSE)),0);
3193 geniCodeAssign(left,
3194 geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
3196 geniCodeRValue(right,FALSE)),0);
3199 geniCodeAssign (left,
3200 geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
3202 geniCodeRValue(right,FALSE),
3204 operandType(left)),0);
3207 geniCodeAssign (left,
3208 geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3210 geniCodeRValue(right,FALSE),
3212 operandType(left)),0);
3215 geniCodeAssign (left,
3216 geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3218 geniCodeRValue(right,FALSE),
3220 operandType(left)),0);
3222 return geniCodeRValue(right,FALSE);
3225 return geniCodeCall (ast2iCode(tree->left),
3228 geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3229 return ast2iCode (tree->right);
3232 geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3233 return ast2iCode (tree->right);
3236 geniCodeFunctionBody ( tree );
3240 geniCodeReturn (right);
3248 geniCodeSwitch (tree);
3252 geniCodeInline (tree);
3259 /*-----------------------------------------------------------------*/
3260 /* reverseICChain - gets from the list and creates a linkedlist */
3261 /*-----------------------------------------------------------------*/
3262 iCode *reverseiCChain ()
3264 iCode *loop = NULL ;
3265 iCode *prev = NULL ;
3267 while ((loop = getSet(&iCodeChain))) {
3278 /*-----------------------------------------------------------------*/
3279 /* iCodeFromAst - given an ast will convert it to iCode */
3280 /*-----------------------------------------------------------------*/
3281 iCode *iCodeFromAst ( ast *tree )
3283 returnLabel = newiTempLabel("_return");
3284 entryLabel = newiTempLabel("_entry") ;
3286 return reverseiCChain ();