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)
1570 /* if they are both literal then we know the result */
1571 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1572 return operandFromValue (valMult(left->operand.valOperand,
1573 right->operand.valOperand));
1575 resType = usualBinaryConversions(&left, &right);
1577 /* if the right is a literal & power of 2 */
1578 /* then make it a left shift */
1579 if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
1580 (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand))))
1581 ic = newiCode(LEFT_OP, left,operandFromLit(p2)); /* left shift */
1583 ic = newiCode('*',left,right); /* normal multiplication */
1584 /* if the size left or right > 1 then support routine */
1585 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1589 IC_RESULT(ic) = newiTempOperand(resType,1);
1592 return IC_RESULT(ic) ;
1595 /*-----------------------------------------------------------------*/
1596 /* geniCodeDivision - gen intermediate code for division */
1597 /*-----------------------------------------------------------------*/
1598 operand *geniCodeDivision (operand *left, operand *right)
1603 sym_link *rtype = operandType(right);
1604 sym_link *retype= getSpec(rtype);
1605 sym_link *ltype = operandType(left);
1606 sym_link *letype= getSpec(ltype);
1608 resType = usualBinaryConversions(&left, &right);
1610 /* if the right is a literal & power of 2 */
1611 /* then make it a right shift */
1612 if (IS_LITERAL(retype) &&
1613 !IS_FLOAT(letype) &&
1614 (p2 = powof2 ((unsigned long)
1615 floatFromVal(right->operand.valOperand))))
1616 ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
1618 ic = newiCode('/',left,right); /* normal division */
1619 /* if the size left or right > 1 then support routine */
1620 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1623 IC_RESULT(ic) = newiTempOperand(resType,0);
1626 return IC_RESULT(ic) ;
1628 /*-----------------------------------------------------------------*/
1629 /* geniCodeModulus - gen intermediate code for modulus */
1630 /*-----------------------------------------------------------------*/
1631 operand *geniCodeModulus (operand *left, operand *right)
1637 /* if they are both literal then we know the result */
1638 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1639 return operandFromValue (valMod(left->operand.valOperand,
1640 right->operand.valOperand));
1642 resType = usualBinaryConversions(&left, &right);
1644 /* now they are the same size */
1645 ic = newiCode('%',left,right);
1647 /* if the size left or right > 1 then support routine */
1648 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1650 IC_RESULT(ic) = newiTempOperand(resType,0);
1653 return IC_RESULT(ic) ;
1656 /*-----------------------------------------------------------------*/
1657 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1658 /*-----------------------------------------------------------------*/
1659 operand *geniCodePtrPtrSubtract (operand *left, operand *right)
1665 /* if they are both literals then */
1666 if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
1667 result = operandFromValue (valMinus(left->operand.valOperand,
1668 right->operand.valOperand));
1672 ic = newiCode('-',left,right);
1674 IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
1678 return geniCodeDivision (result,
1679 operandFromLit(getSize(ltype->next)));
1682 /*-----------------------------------------------------------------*/
1683 /* geniCodeSubtract - generates code for subtraction */
1684 /*-----------------------------------------------------------------*/
1685 operand *geniCodeSubtract (operand *left, operand *right)
1692 /* if they both pointers then */
1693 if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
1694 (IS_PTR(rtype) || IS_ARRAY(rtype)))
1695 return geniCodePtrPtrSubtract (left,right);
1697 /* if they are both literal then we know the result */
1698 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1699 && left->isLiteral && right->isLiteral)
1700 return operandFromValue (valMinus(left->operand.valOperand,
1701 right->operand.valOperand));
1703 /* if left is an array or pointer */
1704 if ( IS_PTR(ltype) || IS_ARRAY(ltype) ) {
1705 isarray = left->isaddr ;
1706 right = geniCodeMultiply (right,
1707 operandFromLit(getSize(ltype->next)));
1708 resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
1710 else { /* make them the same size */
1711 resType = usualBinaryConversions(&left, &right);
1714 ic = newiCode('-',left,right);
1716 IC_RESULT(ic)= newiTempOperand(resType,1);
1717 IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
1719 /* if left or right is a float */
1720 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1724 return IC_RESULT(ic) ;
1727 /*-----------------------------------------------------------------*/
1728 /* geniCodeAdd - generates iCode for addition */
1729 /*-----------------------------------------------------------------*/
1730 operand *geniCodeAdd (operand *left, operand *right )
1738 /* if left is an array then array access */
1739 if (IS_ARRAY(ltype))
1740 return geniCodeArray (left,right);
1742 /* if the right side is LITERAL zero */
1743 /* return the left side */
1744 if (IS_LITERAL(retype) && right->isLiteral && !floatFromVal(valFromType(retype)))
1747 /* if left is literal zero return right */
1748 if (IS_LITERAL(letype) && left->isLiteral && !floatFromVal(valFromType(letype)))
1751 /* if left is an array or pointer then size */
1752 if (IS_PTR(ltype)) {
1754 isarray = left->isaddr;
1756 operandFromLit(getSize(ltype->next));
1757 if (getSize(ltype) > 1 && (getSize(rtype) < INTSIZE))
1759 right = geniCodeCast(INTTYPE,right,TRUE);
1761 right = geniCodeMultiply (right ,size);
1763 resType = copyLinkChain(ltype);
1765 else { /* make them the same size */
1766 resType = usualBinaryConversions(&left, &right);
1769 /* if they are both literals then we know */
1770 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1771 && left->isLiteral && right->isLiteral)
1772 return operandFromValue (valPlus(valFromType(letype),
1773 valFromType(retype)));
1775 ic = newiCode('+',left,right);
1777 IC_RESULT(ic) = newiTempOperand(resType,1);
1778 IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
1780 /* if left or right is a float then support
1782 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1787 return IC_RESULT(ic) ;
1791 /*-----------------------------------------------------------------*/
1792 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1793 /*-----------------------------------------------------------------*/
1794 sym_link *aggrToPtr ( sym_link *type, bool force)
1800 if (IS_PTR(type) && !force)
1803 etype = getSpec(type);
1807 /* if the output class is generic */
1808 if ((DCL_TYPE(ptype) = PTR_TYPE(SPEC_OCLS(etype))) == CPOINTER)
1809 DCL_PTR_CONST(ptype) = port->mem.code_ro;
1811 /* if the variable was declared a constant */
1812 /* then the pointer points to a constant */
1813 if (IS_CONSTANT(etype) )
1814 DCL_PTR_CONST(ptype) = 1;
1816 /* the variable was volatile then pointer to volatile */
1817 if (IS_VOLATILE(etype))
1818 DCL_PTR_VOLATILE(ptype) = 1;
1822 /*-----------------------------------------------------------------*/
1823 /* geniCodeArray2Ptr - array to pointer */
1824 /*-----------------------------------------------------------------*/
1825 operand *geniCodeArray2Ptr (operand *op)
1827 sym_link *optype = operandType(op);
1828 sym_link *opetype = getSpec(optype);
1830 /* set the pointer depending on the storage class */
1831 if ((DCL_TYPE(optype) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1832 DCL_PTR_CONST(optype) = port->mem.code_ro;
1835 /* if the variable was declared a constant */
1836 /* then the pointer points to a constant */
1837 if (IS_CONSTANT(opetype) )
1838 DCL_PTR_CONST(optype) = 1;
1840 /* the variable was volatile then pointer to volatile */
1841 if (IS_VOLATILE(opetype))
1842 DCL_PTR_VOLATILE(optype) = 1;
1848 /*-----------------------------------------------------------------*/
1849 /* geniCodeArray - array access */
1850 /*-----------------------------------------------------------------*/
1851 operand *geniCodeArray (operand *left,operand *right)
1854 sym_link *ltype = operandType(left);
1856 if (IS_PTR(ltype)) {
1857 if (IS_PTR(ltype->next) && left->isaddr)
1859 left = geniCodeRValue(left,FALSE);
1861 return geniCodeDerefPtr(geniCodeAdd(left,right));
1865 right = usualUnaryConversions(right);
1866 right = geniCodeMultiply(right,
1867 operandFromLit(getSize(ltype->next)));
1869 /* we can check for limits here */
1870 if (isOperandLiteral(right) &&
1873 (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
1874 werror(E_ARRAY_BOUND);
1875 right = operandFromLit(0);
1878 ic = newiCode('+',left,right);
1880 IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) &&
1881 !IS_AGGREGATE(ltype->next) &&
1882 !IS_PTR(ltype->next))
1883 ? ltype : ltype->next),0);
1885 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
1887 return IC_RESULT(ic) ;
1890 /*-----------------------------------------------------------------*/
1891 /* geniCodeStruct - generates intermediate code for structres */
1892 /*-----------------------------------------------------------------*/
1893 operand *geniCodeStruct (operand *left, operand *right, bool islval)
1896 sym_link *type = operandType(left);
1897 sym_link *etype = getSpec(type);
1899 symbol *element = getStructElement(SPEC_STRUCT(etype),
1900 right->operand.symOperand);
1902 /* add the offset */
1903 ic = newiCode('+',left,operandFromLit(element->offset));
1905 IC_RESULT(ic) = newiTempOperand(element->type,0);
1907 /* preserve the storage & output class of the struct */
1908 /* as well as the volatile attribute */
1909 retype = getSpec(operandType(IC_RESULT(ic)));
1910 SPEC_SCLS(retype) = SPEC_SCLS(etype);
1911 SPEC_OCLS(retype) = SPEC_OCLS(etype);
1912 SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);
1914 if (IS_PTR(element->type))
1915 setOperandType(IC_RESULT(ic),aggrToPtr(operandType(IC_RESULT(ic)),TRUE));
1917 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(element->type));
1921 return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
1924 /*-----------------------------------------------------------------*/
1925 /* geniCodePostInc - generate int code for Post increment */
1926 /*-----------------------------------------------------------------*/
1927 operand *geniCodePostInc (operand *op)
1931 sym_link *optype = operandType(op);
1933 operand *rv = (IS_ITEMP(op) ?
1934 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1936 sym_link *rvtype = operandType(rv);
1939 /* if this is not an address we have trouble */
1940 if ( ! op->isaddr ) {
1941 werror (E_LVALUE_REQUIRED,"++");
1945 rOp = newiTempOperand(rvtype,0);
1951 geniCodeAssign(rOp,rv,0);
1953 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1954 ic = newiCode('+',rv,operandFromLit(size));
1955 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1958 geniCodeAssign(op,result,0);
1964 /*-----------------------------------------------------------------*/
1965 /* geniCodePreInc - generate code for preIncrement */
1966 /*-----------------------------------------------------------------*/
1967 operand *geniCodePreInc (operand *op)
1970 sym_link *optype = operandType(op);
1971 operand *rop = (IS_ITEMP(op) ?
1972 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1974 sym_link *roptype = operandType(rop);
1978 if ( ! op->isaddr ) {
1979 werror(E_LVALUE_REQUIRED,"++");
1984 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1985 ic = newiCode('+',rop,operandFromLit(size));
1986 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1990 return geniCodeAssign(op,result,0) ;
1993 /*-----------------------------------------------------------------*/
1994 /* geniCodePostDec - generates code for Post decrement */
1995 /*-----------------------------------------------------------------*/
1996 operand *geniCodePostDec (operand *op)
2000 sym_link *optype = operandType(op);
2002 operand *rv = (IS_ITEMP(op) ?
2003 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
2005 sym_link *rvtype = operandType(rv);
2008 /* if this is not an address we have trouble */
2009 if ( ! op->isaddr ) {
2010 werror (E_LVALUE_REQUIRED,"++");
2014 rOp = newiTempOperand(rvtype,0);
2020 geniCodeAssign(rOp,rv,0);
2022 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
2023 ic = newiCode('-',rv,operandFromLit(size));
2024 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
2027 geniCodeAssign(op,result,0);
2033 /*-----------------------------------------------------------------*/
2034 /* geniCodePreDec - generate code for pre decrement */
2035 /*-----------------------------------------------------------------*/
2036 operand *geniCodePreDec (operand *op)
2039 sym_link *optype = operandType(op);
2040 operand *rop = (IS_ITEMP(op) ?
2041 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
2043 sym_link *roptype = operandType(rop);
2047 if ( ! op->isaddr ) {
2048 werror(E_LVALUE_REQUIRED,"++");
2053 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
2054 ic = newiCode('-',rop,operandFromLit(size));
2055 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
2059 return geniCodeAssign(op,result,0) ;
2063 /*-----------------------------------------------------------------*/
2064 /* geniCodeBitwise - gen int code for bitWise operators */
2065 /*-----------------------------------------------------------------*/
2066 operand *geniCodeBitwise (operand *left, operand *right,
2067 int oper, sym_link *resType)
2071 left = geniCodeCast(resType,left,TRUE);
2072 right= geniCodeCast(resType,right,TRUE);
2074 ic = newiCode(oper,left,right);
2075 IC_RESULT(ic) = newiTempOperand(resType,0);
2078 return IC_RESULT(ic) ;
2081 /*-----------------------------------------------------------------*/
2082 /* geniCodeAddressOf - gens icode for '&' address of operator */
2083 /*-----------------------------------------------------------------*/
2084 operand *geniCodeAddressOf (operand *op)
2088 sym_link *optype = operandType(op);
2089 sym_link *opetype= getSpec(optype);
2091 /* lvalue check already done in decorateType */
2092 /* this must be a lvalue */
2093 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2094 /* werror (E_LVALUE_REQUIRED,"&"); */
2099 p->class = DECLARATOR ;
2101 /* set the pointer depending on the storage class */
2102 if ((DCL_TYPE(p) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
2103 DCL_PTR_CONST(p) = port->mem.code_ro;
2105 /* make sure we preserve the const & volatile */
2106 if (IS_CONSTANT(opetype))
2107 DCL_PTR_CONST(p) = 1;
2109 if (IS_VOLATILE(opetype))
2110 DCL_PTR_VOLATILE(p) = 1;
2112 p->next = copyLinkChain(optype);
2114 /* if already a temp */
2116 setOperandType (op,p);
2121 /* other wise make this of the type coming in */
2122 ic = newiCode(ADDRESS_OF,op,NULL);
2123 IC_RESULT(ic) = newiTempOperand(p,1);
2124 IC_RESULT(ic)->isaddr = 0;
2126 return IC_RESULT(ic);
2128 /*-----------------------------------------------------------------*/
2129 /* setOClass - sets the output class depending on the pointer type */
2130 /*-----------------------------------------------------------------*/
2131 void setOClass (sym_link *ptr, sym_link *spec)
2133 switch (DCL_TYPE(ptr)) {
2135 SPEC_OCLS(spec) = data ;
2139 SPEC_OCLS(spec) = generic;
2143 SPEC_OCLS(spec) = xdata ;
2147 SPEC_OCLS(spec) = code ;
2151 SPEC_OCLS(spec) = idata;
2155 SPEC_OCLS(spec) = xstack;
2159 SPEC_OCLS(spec) = eeprom;
2168 /*-----------------------------------------------------------------*/
2169 /* geniCodeDerefPtr - dereference pointer with '*' */
2170 /*-----------------------------------------------------------------*/
2171 operand *geniCodeDerefPtr (operand *op)
2173 sym_link *rtype , *retype ;
2174 sym_link *optype = operandType(op);
2176 /* if this is a pointer then generate the rvalue */
2177 if (IS_PTR(optype)) {
2178 if (IS_TRUE_SYMOP(op)) {
2180 op = geniCodeRValue(op,TRUE);
2183 op = geniCodeRValue(op,TRUE);
2186 /* now get rid of the pointer part */
2187 if (lvaluereq && IS_ITEMP(op) )
2189 retype = getSpec(rtype = copyLinkChain(optype)) ;
2193 retype = getSpec(rtype = copyLinkChain(optype->next)) ;
2196 /* if this is a pointer then outputclass needs 2b updated */
2198 setOClass(optype,retype);
2200 op->isGptr = IS_GENPTR(optype);
2202 /* if the pointer was declared as a constant */
2203 /* then we cannot allow assignment to the derefed */
2204 if (IS_PTR_CONST(optype))
2205 SPEC_CONST(retype) = 1;
2207 op->isaddr = (IS_PTR(rtype) ||
2214 op = geniCodeRValue(op,TRUE);
2216 setOperandType(op,rtype);
2221 /*-----------------------------------------------------------------*/
2222 /* geniCodeUnaryMinus - does a unary minus of the operand */
2223 /*-----------------------------------------------------------------*/
2224 operand *geniCodeUnaryMinus (operand *op)
2227 sym_link *optype = operandType(op);
2229 if (IS_LITERAL(optype))
2230 return operandFromLit(- floatFromVal(op->operand.valOperand));
2232 ic = newiCode(UNARYMINUS,op,NULL);
2233 IC_RESULT(ic) = newiTempOperand(optype,0);
2235 return IC_RESULT(ic);
2238 /*-----------------------------------------------------------------*/
2239 /* geniCodeLeftShift - gen i code for left shift */
2240 /*-----------------------------------------------------------------*/
2241 operand *geniCodeLeftShift (operand *left, operand *right)
2245 /* Note that we don't use the usual binary conversions for the
2246 * shift operations, in accordance with our ANSI friends.
2248 if (options.ANSIint)
2250 right = usualUnaryConversions(right);
2251 left = usualUnaryConversions(left);
2254 ic = newiCode(LEFT_OP,left,right);
2255 IC_RESULT(ic) = newiTempOperand(operandType(left),0);
2257 return IC_RESULT(ic) ;
2260 /*-----------------------------------------------------------------*/
2261 /* geniCodeRightShift - gen i code for right shift */
2262 /*-----------------------------------------------------------------*/
2263 operand *geniCodeRightShift (operand *left, operand *right)
2267 /* Note that we don't use the usual binary conversions for the
2268 * shift operations, in accordance with our ANSI friends.
2270 if (options.ANSIint)
2272 right = usualUnaryConversions(right);
2273 left = usualUnaryConversions(left);
2276 ic = newiCode(RIGHT_OP,left,right);
2277 IC_RESULT(ic) = newiTempOperand(operandType(left),0);
2279 return IC_RESULT(ic) ;
2282 #if defined(__BORLANDC__) || defined(_MSC_VER)
2283 #define LONG_LONG __int64
2285 #define LONG_LONG long long
2288 /*-----------------------------------------------------------------*/
2289 /* geniCodeLogic- logic code */
2290 /*-----------------------------------------------------------------*/
2291 operand *geniCodeLogic (operand *left, operand *right, int op )
2295 sym_link *rtype = operandType(right);
2296 sym_link *ltype = operandType(left);
2298 /* left is integral type and right is literal then
2299 check if the literal value is within bounds */
2300 if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2301 int nbits = bitsForType(ltype);
2302 long v = operandLitValue(right);
2304 if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2305 werror(W_CONST_RANGE," compare operation ");
2308 ctype = usualBinaryConversions(&left, &right);
2310 ic = newiCode(op,left,right);
2311 IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2313 /* if comparing anything greater than one byte
2314 and not a '==' || '!=' || '&&' || '||' (these
2316 if (getSize(ctype) > 1 &&
2324 return IC_RESULT(ic);
2327 /*-----------------------------------------------------------------*/
2328 /* geniCodeUnary - for a a generic unary operation */
2329 /*-----------------------------------------------------------------*/
2330 operand *geniCodeUnary (operand *op, int oper )
2332 iCode *ic = newiCode (oper,op,NULL);
2334 IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2336 return IC_RESULT(ic) ;
2339 /*-----------------------------------------------------------------*/
2340 /* geniCodeConditional - geniCode for '?' ':' operation */
2341 /*-----------------------------------------------------------------*/
2342 operand *geniCodeConditional (ast *tree)
2345 symbol *falseLabel = newiTempLabel(NULL);
2346 symbol *exitLabel = newiTempLabel(NULL);
2347 operand *cond = ast2iCode(tree->left);
2348 operand *true, *false , *result;
2350 ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2354 true = ast2iCode(tree->right->left);
2356 /* move the value to a new Operand */
2357 result = newiTempOperand(operandType(true),0);
2358 geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2360 /* generate an unconditional goto */
2361 geniCodeGoto(exitLabel);
2363 /* now for the right side */
2364 geniCodeLabel(falseLabel);
2366 false = ast2iCode(tree->right->right);
2367 geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2369 /* create the exit label */
2370 geniCodeLabel(exitLabel);
2375 /*-----------------------------------------------------------------*/
2376 /* geniCodeAssign - generate code for assignment */
2377 /*-----------------------------------------------------------------*/
2378 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2381 sym_link *ltype = operandType(left);
2382 sym_link *rtype = operandType(right);
2384 if (!left->isaddr && !IS_ITEMP(left)) {
2385 werror(E_LVALUE_REQUIRED,"assignment");
2389 /* left is integral type and right is literal then
2390 check if the literal value is within bounds */
2391 if (IS_INTEGRAL(ltype) && right->type == VALUE && IS_LITERAL(rtype)) {
2392 int nbits = bitsForType(ltype);
2393 long v = operandLitValue(right);
2395 if (v > ((LONG_LONG)1 << nbits) && v > 0)
2396 werror(W_CONST_RANGE," = operation");
2399 /* if the left & right type don't exactly match */
2400 /* if pointer set then make sure the check is
2401 done with the type & not the pointer */
2402 /* then cast rights type to left */
2404 /* first check the type for pointer assignement */
2405 if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2406 checkType(ltype,rtype)<0) {
2407 if (checkType(ltype->next,rtype) < 0)
2408 right = geniCodeCast(ltype->next,right,TRUE);
2410 if (checkType(ltype,rtype) < 0 )
2411 right = geniCodeCast(ltype,right,TRUE);
2413 /* if left is a true symbol & ! volatile
2414 create an assignment to temporary for
2415 the right & then assign this temporary
2416 to the symbol this is SSA . isn't it simple
2417 and folks have published mountains of paper on it */
2418 if (IS_TRUE_SYMOP(left) &&
2419 !isOperandVolatile(left,FALSE) &&
2420 isOperandGlobal(left)) {
2423 if (IS_TRUE_SYMOP(right))
2424 sym = OP_SYMBOL(right);
2425 ic = newiCode('=',NULL,right);
2426 IC_RESULT(ic) = right = newiTempOperand(ltype,0);
2427 SPIL_LOC(right) = sym ;
2431 ic = newiCode('=',NULL,right);
2432 IC_RESULT(ic) = left;
2435 /* if left isgptr flag is set then support
2436 routine will be required */
2440 ic->nosupdate = nosupdate;
2444 /*-----------------------------------------------------------------*/
2445 /* geniCodeSEParms - generate code for side effecting fcalls */
2446 /*-----------------------------------------------------------------*/
2447 static void geniCodeSEParms (ast *parms)
2452 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2453 geniCodeSEParms (parms->left) ;
2454 geniCodeSEParms (parms->right);
2458 /* hack don't like this but too lazy to think of
2460 if (IS_ADDRESS_OF_OP(parms))
2461 parms->left->lvalue = 1;
2463 if (IS_CAST_OP(parms) &&
2464 IS_PTR(parms->ftype) &&
2465 IS_ADDRESS_OF_OP(parms->right))
2466 parms->right->left->lvalue = 1;
2468 parms->opval.oprnd =
2469 geniCodeRValue(ast2iCode (parms),FALSE);
2471 parms->type = EX_OPERAND ;
2474 /*-----------------------------------------------------------------*/
2475 /* geniCodeParms - generates parameters */
2476 /*-----------------------------------------------------------------*/
2477 static void geniCodeParms ( ast *parms , int *stack, sym_link *fetype, symbol *func)
2485 /* if this is a param node then do the left & right */
2486 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2487 geniCodeParms (parms->left, stack,fetype,func) ;
2488 geniCodeParms (parms->right, stack,fetype,func);
2492 /* get the parameter value */
2493 if (parms->type == EX_OPERAND)
2494 pval = parms->opval.oprnd ;
2496 /* maybe this else should go away ?? */
2497 /* hack don't like this but too lazy to think of
2499 if (IS_ADDRESS_OF_OP(parms))
2500 parms->left->lvalue = 1;
2502 if (IS_CAST_OP(parms) &&
2503 IS_PTR(parms->ftype) &&
2504 IS_ADDRESS_OF_OP(parms->right))
2505 parms->right->left->lvalue = 1;
2507 pval = geniCodeRValue(ast2iCode (parms),FALSE);
2510 /* if register parm then make it a send */
2511 if (((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2512 IS_REGPARM(parms->etype)) && !func->hasVargs ) {
2513 ic = newiCode(SEND,pval,NULL);
2516 /* now decide whether to push or assign */
2517 if (!(options.stackAuto || IS_RENT(fetype))) {
2520 operand *top = operandFromSymbol(parms->argSym);
2521 geniCodeAssign(top,pval,1);
2524 sym_link *p = operandType(pval);
2526 ic = newiCode(IPUSH,pval,NULL);
2528 /* update the stack adjustment */
2529 *stack += getSize(IS_AGGREGATE(p)? aggrToPtr(p,FALSE):p);
2536 /*-----------------------------------------------------------------*/
2537 /* geniCodeCall - generates temp code for calling */
2538 /*-----------------------------------------------------------------*/
2539 operand *geniCodeCall (operand *left, ast *parms)
2543 sym_link *type, *etype;
2546 /* take care of parameters with side-effecting
2547 function calls in them, this is required to take care
2548 of overlaying function parameters */
2549 geniCodeSEParms ( parms );
2551 /* first the parameters */
2552 geniCodeParms ( parms , &stack , getSpec(operandType(left)), OP_SYMBOL(left));
2554 /* now call : if symbol then pcall */
2556 ic = newiCode(PCALL,left,NULL);
2558 ic = newiCode(CALL,left,NULL);
2560 IC_ARGS(ic) = left->operand.symOperand->args ;
2561 type = copyLinkChain(operandType(left)->next);
2562 etype = getSpec(type);
2563 SPEC_EXTR(etype) = 0;
2564 IC_RESULT(ic) = result = newiTempOperand(type,1);
2568 /* stack adjustment after call */
2569 left->parmBytes = stack;
2574 /*-----------------------------------------------------------------*/
2575 /* geniCodeReceive - generate intermediate code for "receive" */
2576 /*-----------------------------------------------------------------*/
2577 static void geniCodeReceive (value *args)
2579 /* for all arguments that are passed in registers */
2582 if (IS_REGPARM(args->etype)) {
2583 operand *opr = operandFromValue(args);
2585 symbol *sym = OP_SYMBOL(opr);
2588 /* we will use it after all optimizations
2589 and before liveRange calculation */
2590 if (!sym->addrtaken && !IS_VOLATILE(sym->etype)) {
2592 if (IN_FARSPACE(SPEC_OCLS(sym->etype)) &&
2593 options.stackAuto == 0 &&
2596 opl = newiTempOperand(args->type,0);
2598 sym->reqv->key = sym->key ;
2599 OP_SYMBOL(sym->reqv)->key = sym->key;
2600 OP_SYMBOL(sym->reqv)->isreqv = 1;
2601 OP_SYMBOL(sym->reqv)->islocal= 0;
2602 SPIL_LOC(sym->reqv) = sym;
2606 ic = newiCode(RECEIVE,NULL,NULL);
2607 currFunc->recvSize = getSize(sym->etype);
2608 IC_RESULT(ic) = opr;
2616 /*-----------------------------------------------------------------*/
2617 /* geniCodeFunctionBody - create the function body */
2618 /*-----------------------------------------------------------------*/
2619 void geniCodeFunctionBody (ast *tree)
2626 /* reset the auto generation */
2632 func = ast2iCode(tree->left);
2633 fetype = getSpec(operandType(func));
2635 savelineno = lineno;
2636 lineno = OP_SYMBOL(func)->lineDef;
2637 /* create an entry label */
2638 geniCodeLabel(entryLabel);
2639 lineno = savelineno;
2641 /* create a proc icode */
2642 ic = newiCode(FUNCTION,func,NULL);
2643 /* if the function has parmas then */
2644 /* save the parameters information */
2645 ic->argLabel.args = tree->values.args ;
2646 ic->lineno = OP_SYMBOL(func)->lineDef;
2650 /* for all parameters that are passed
2651 on registers add a "receive" */
2652 geniCodeReceive( tree->values.args );
2654 /* generate code for the body */
2655 ast2iCode(tree->right);
2657 /* create a label for return */
2658 geniCodeLabel(returnLabel);
2660 /* now generate the end proc */
2661 ic = newiCode(ENDFUNCTION,func,NULL);
2666 /*-----------------------------------------------------------------*/
2667 /* geniCodeReturn - gen icode for 'return' statement */
2668 /*-----------------------------------------------------------------*/
2669 void geniCodeReturn (operand *op)
2673 /* if the operand is present force an rvalue */
2675 op = geniCodeRValue(op,FALSE);
2677 ic = newiCode(RETURN,op,NULL);
2681 /*-----------------------------------------------------------------*/
2682 /* geniCodeIfx - generates code for extended if statement */
2683 /*-----------------------------------------------------------------*/
2684 void geniCodeIfx (ast *tree)
2687 operand *condition = ast2iCode(tree->left);
2690 /* if condition is null then exit */
2694 condition = geniCodeRValue(condition,FALSE);
2696 cetype = getSpec(operandType(condition));
2697 /* if the condition is a literal */
2698 if (IS_LITERAL(cetype)) {
2699 if (floatFromVal(condition->operand.valOperand)) {
2700 if (tree->trueLabel)
2701 geniCodeGoto(tree->trueLabel);
2706 if (tree->falseLabel)
2707 geniCodeGoto (tree->falseLabel);
2714 if ( tree->trueLabel ) {
2715 ic = newiCodeCondition(condition,
2720 if ( tree->falseLabel)
2721 geniCodeGoto(tree->falseLabel);
2724 ic = newiCodeCondition (condition,
2731 ast2iCode(tree->right);
2734 /*-----------------------------------------------------------------*/
2735 /* geniCodeJumpTable - tries to create a jump table for switch */
2736 /*-----------------------------------------------------------------*/
2737 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2739 int min = 0 ,max = 0, t, cnt = 0;
2744 set *labels = NULL ;
2746 if (!tree || !caseVals)
2749 /* the criteria for creating a jump table is */
2750 /* all integer numbers between the maximum & minimum must */
2751 /* be present , the maximum value should not exceed 255 */
2752 min = max = (int)floatFromVal(vch = caseVals);
2753 sprintf(buffer,"_case_%d_%d",
2754 tree->values.switchVals.swNum,
2756 addSet(&labels,newiTempLabel(buffer));
2758 /* if there is only one case value then no need */
2759 if (!(vch = vch->next ))
2763 if (((t = (int)floatFromVal(vch)) - max) != 1)
2765 sprintf(buffer,"_case_%d_%d",
2766 tree->values.switchVals.swNum,
2768 addSet(&labels,newiTempLabel(buffer));
2774 /* if the number of case statements <= 2 then */
2775 /* it is not economical to create the jump table */
2776 /* since two compares are needed for boundary conditions */
2777 if ((! optimize.noJTabBoundary && cnt <= 2) || max > (255/3))
2780 if ( tree->values.switchVals.swDefault )
2781 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2783 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2785 falseLabel = newiTempLabel (buffer);
2787 /* so we can create a jumptable */
2788 /* first we rule out the boundary conditions */
2789 /* if only optimization says so */
2790 if ( ! optimize.noJTabBoundary ) {
2791 sym_link *cetype = getSpec(operandType(cond));
2792 /* no need to check the lower bound if
2793 the condition is unsigned & minimum value is zero */
2794 if (!( min == 0 && SPEC_USIGN(cetype))) {
2795 boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2796 ic = newiCodeCondition (boundary,falseLabel,NULL);
2800 /* now for upper bounds */
2801 boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2802 ic = newiCodeCondition (boundary,falseLabel,NULL);
2806 /* if the min is not zero then we no make it zero */
2808 cond = geniCodeSubtract(cond,operandFromLit(min));
2809 setOperandType(cond, UCHARTYPE);
2812 /* now create the jumptable */
2813 ic = newiCode(JUMPTABLE,NULL,NULL);
2814 IC_JTCOND(ic) = cond;
2815 IC_JTLABELS(ic) = labels;
2820 /*-----------------------------------------------------------------*/
2821 /* geniCodeSwitch - changes a switch to a if statement */
2822 /*-----------------------------------------------------------------*/
2823 void geniCodeSwitch (ast *tree)
2826 operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2827 value *caseVals = tree->values.switchVals.swVals ;
2828 symbol *trueLabel , *falseLabel;
2830 /* if we can make this a jump table */
2831 if ( geniCodeJumpTable (cond,caseVals,tree) )
2832 goto jumpTable ; /* no need for the comparison */
2834 /* for the cases defined do */
2837 operand *compare = geniCodeLogic (cond,
2838 operandFromValue(caseVals),
2841 sprintf(buffer,"_case_%d_%d",
2842 tree->values.switchVals.swNum,
2843 (int) floatFromVal(caseVals));
2844 trueLabel = newiTempLabel(buffer);
2846 ic = newiCodeCondition(compare,trueLabel,NULL);
2848 caseVals = caseVals->next;
2853 /* if default is present then goto break else break */
2854 if ( tree->values.switchVals.swDefault )
2855 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2857 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2859 falseLabel = newiTempLabel (buffer);
2860 geniCodeGoto(falseLabel);
2863 ast2iCode(tree->right);
2866 /*-----------------------------------------------------------------*/
2867 /* geniCodeInline - intermediate code for inline assembler */
2868 /*-----------------------------------------------------------------*/
2869 static void geniCodeInline (ast *tree)
2873 ic = newiCode(INLINEASM,NULL,NULL);
2874 IC_INLINE(ic) = tree->values.inlineasm;
2878 /*-----------------------------------------------------------------*/
2879 /* ast2iCode - creates an icodeList from an ast */
2880 /*-----------------------------------------------------------------*/
2881 operand *ast2iCode (ast *tree)
2883 operand *left = NULL;
2884 operand *right= NULL;
2889 /* set the global variables for filename & line number */
2890 if ( tree->filename )
2891 filename = tree->filename ;
2893 lineno = tree->lineno ;
2895 block = tree->block ;
2897 scopeLevel = tree->level;
2899 if (tree->type == EX_VALUE )
2900 return operandFromValue(tree->opval.val);
2902 if (tree->type == EX_LINK )
2903 return operandFromLink (tree->opval.lnk);
2905 /* if we find a nullop */
2906 if (tree->type == EX_OP &&
2907 ( tree->opval.op == NULLOP ||
2908 tree->opval.op == BLOCK )) {
2909 ast2iCode (tree->left);
2910 ast2iCode (tree->right);
2914 /* special cases for not evaluating */
2915 if ( tree->opval.op != ':' &&
2916 tree->opval.op != '?' &&
2917 tree->opval.op != CALL &&
2918 tree->opval.op != IFX &&
2919 tree->opval.op != LABEL &&
2920 tree->opval.op != GOTO &&
2921 tree->opval.op != SWITCH &&
2922 tree->opval.op != FUNCTION &&
2923 tree->opval.op != INLINEASM ) {
2925 if (IS_ASSIGN_OP(tree->opval.op) ||
2926 IS_DEREF_OP(tree) ||
2927 (tree->opval.op == '&' && !tree->right) ||
2928 tree->opval.op == PTR_OP) {
2930 if ((IS_ARRAY_OP(tree->left) && IS_ARRAY_OP(tree->left->left)) ||
2931 (IS_DEREF_OP(tree) && IS_ARRAY_OP(tree->left)))
2933 int olvr = lvaluereq ;
2935 left = operandFromAst(tree->left);
2936 lvaluereq = olvr - 1;
2938 left = operandFromAst(tree->left);
2941 if (IS_DEREF_OP(tree) && IS_DEREF_OP(tree->left))
2942 left = geniCodeRValue(left,TRUE);
2944 left = operandFromAst(tree->left);
2946 if (tree->opval.op == INC_OP ||
2947 tree->opval.op == DEC_OP) {
2949 right= operandFromAst(tree->right);
2952 right= operandFromAst(tree->right);
2956 /* now depending on the type of operand */
2957 /* this will be a biggy */
2958 switch (tree->opval.op) {
2960 case '[' : /* array operation */
2962 sym_link *ltype = operandType(left);
2963 left= geniCodeRValue (left,IS_PTR(ltype->next) ? TRUE : FALSE);
2964 right=geniCodeRValue (right,TRUE);
2967 return geniCodeArray (left,right);
2969 case '.' : /* structure dereference */
2970 if (IS_PTR(operandType(left)))
2971 left = geniCodeRValue(left,TRUE);
2973 left = geniCodeRValue(left,FALSE);
2975 return geniCodeStruct (left,right,tree->lvalue);
2977 case PTR_OP: /* structure pointer dereference */
2980 pType = operandType(left);
2981 left = geniCodeRValue(left,TRUE);
2983 setOClass (pType,getSpec(operandType(left)));
2986 return geniCodeStruct (left, right,tree->lvalue);
2988 case INC_OP: /* increment operator */
2990 return geniCodePostInc (left);
2992 return geniCodePreInc (right);
2994 case DEC_OP: /* decrement operator */
2996 return geniCodePostDec (left);
2998 return geniCodePreDec (right);
3000 case '&' : /* bitwise and or address of operator */
3001 if ( right ) { /* this is a bitwise operator */
3002 left= geniCodeRValue(left,FALSE);
3003 right= geniCodeRValue(right,FALSE);
3004 return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
3006 return geniCodeAddressOf (left);
3008 case '|': /* bitwise or & xor */
3010 return geniCodeBitwise (geniCodeRValue(left,FALSE),
3011 geniCodeRValue(right,FALSE),
3016 return geniCodeDivision (geniCodeRValue(left,FALSE),
3017 geniCodeRValue(right,FALSE));
3020 return geniCodeModulus (geniCodeRValue(left,FALSE),
3021 geniCodeRValue(right,FALSE));
3024 return geniCodeMultiply (geniCodeRValue(left,FALSE),
3025 geniCodeRValue(right,FALSE));
3027 return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
3031 return geniCodeSubtract (geniCodeRValue(left,FALSE),
3032 geniCodeRValue(right,FALSE));
3034 return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
3038 return geniCodeAdd (geniCodeRValue(left,FALSE),
3039 geniCodeRValue(right,FALSE));
3041 return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
3044 return geniCodeLeftShift (geniCodeRValue(left,FALSE),
3045 geniCodeRValue(right,FALSE));
3048 return geniCodeRightShift (geniCodeRValue(left,FALSE),
3049 geniCodeRValue(right,FALSE));
3051 return geniCodeCast (operandType(left),
3052 geniCodeRValue(right,FALSE),FALSE);
3058 return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
3062 operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
3063 setOperandType(op, UCHARTYPE);
3074 return geniCodeLogic (geniCodeRValue(left,FALSE),
3075 geniCodeRValue(right,FALSE),
3078 return geniCodeConditional (tree);
3081 return operandFromLit(getSize(tree->right->ftype));
3085 sym_link *rtype = operandType(right);
3086 sym_link *ltype = operandType(left);
3087 if (IS_PTR(rtype) && IS_ITEMP(right)
3088 && right->isaddr && checkType(rtype->next,ltype)==1)
3089 right = geniCodeRValue(right,TRUE);
3091 right = geniCodeRValue(right,FALSE);
3093 geniCodeAssign (left,right,0);
3098 geniCodeAssign(left,
3099 geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
3101 geniCodeRValue(right,FALSE)),0);
3105 geniCodeAssign(left,
3106 geniCodeDivision(geniCodeRValue(operandFromOperand(left),
3108 geniCodeRValue(right,FALSE)),0);
3111 geniCodeAssign(left,
3112 geniCodeModulus(geniCodeRValue(operandFromOperand(left),
3114 geniCodeRValue(right,FALSE)),0);
3117 sym_link *rtype = operandType(right);
3118 sym_link *ltype = operandType(left);
3119 if (IS_PTR(rtype) && IS_ITEMP(right)
3120 && right->isaddr && checkType(rtype->next,ltype)==1)
3121 right = geniCodeRValue(right,TRUE);
3123 right = geniCodeRValue(right,FALSE);
3126 return geniCodeAssign(left,
3127 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
3133 sym_link *rtype = operandType(right);
3134 sym_link *ltype = operandType(left);
3135 if (IS_PTR(rtype) && IS_ITEMP(right)
3136 && right->isaddr && checkType(rtype->next,ltype)==1) {
3137 right = geniCodeRValue(right,TRUE);
3140 right = geniCodeRValue(right,FALSE);
3143 geniCodeAssign (left,
3144 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
3150 geniCodeAssign (left,
3151 geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
3153 geniCodeRValue(right,FALSE)),0);
3156 geniCodeAssign(left,
3157 geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
3159 geniCodeRValue(right,FALSE)),0);
3162 geniCodeAssign (left,
3163 geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
3165 geniCodeRValue(right,FALSE),
3167 operandType(left)),0);
3170 geniCodeAssign (left,
3171 geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3173 geniCodeRValue(right,FALSE),
3175 operandType(left)),0);
3178 geniCodeAssign (left,
3179 geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3181 geniCodeRValue(right,FALSE),
3183 operandType(left)),0);
3185 return geniCodeRValue(right,FALSE);
3188 return geniCodeCall (ast2iCode(tree->left),
3191 geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3192 return ast2iCode (tree->right);
3195 geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3196 return ast2iCode (tree->right);
3199 geniCodeFunctionBody ( tree );
3203 geniCodeReturn (right);
3211 geniCodeSwitch (tree);
3215 geniCodeInline (tree);
3222 /*-----------------------------------------------------------------*/
3223 /* reverseICChain - gets from the list and creates a linkedlist */
3224 /*-----------------------------------------------------------------*/
3225 iCode *reverseiCChain ()
3227 iCode *loop = NULL ;
3228 iCode *prev = NULL ;
3230 while ((loop = getSet(&iCodeChain))) {
3241 /*-----------------------------------------------------------------*/
3242 /* iCodeFromAst - given an ast will convert it to iCode */
3243 /*-----------------------------------------------------------------*/
3244 iCode *iCodeFromAst ( ast *tree )
3246 returnLabel = newiTempLabel("_return");
3247 entryLabel = newiTempLabel("_entry") ;
3249 return reverseiCChain ();