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 -------------------------------------------------------------------------*/
27 /*-----------------------------------------------------------------*/
28 /* global variables */
30 set *iCodeChain = NULL ;
43 symbol *returnLabel ; /* function return label */
44 symbol *entryLabel ; /* function entry label */
45 /*-----------------------------------------------------------------*/
46 /* forward definition of some functions */
47 operand *geniCodeDivision (operand *,operand *);
48 operand *geniCodeAssign (operand *,operand *,int);
49 operand *geniCodeArray (operand *,operand *);
50 operand *geniCodeArray2Ptr (operand *);
51 operand *geniCodeRValue (operand *, bool );
52 operand *geniCodeDerefPtr (operand *);
54 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
55 /* forward definition of print functions */
56 PRINTFUNC(picGetValueAtAddr);
57 PRINTFUNC(picSetValueAtAddr);
59 PRINTFUNC(picGeneric);
60 PRINTFUNC(picGenericOne);
66 PRINTFUNC(picJumpTable);
68 PRINTFUNC(picReceive);
70 iCodeTable codeTable[] = {
71 { '!' , "not", picGenericOne , NULL },
72 { '~' , "~" , picGenericOne , NULL },
73 { RRC , "rrc", picGenericOne , NULL },
74 { RLC , "rlc", picGenericOne , NULL },
75 { GETHBIT ,"ghbit", picGenericOne , NULL },
76 { UNARYMINUS , "-" , picGenericOne , NULL },
77 { IPUSH , "push",picGenericOne , NULL },
78 { IPOP , "pop", picGenericOne , NULL },
79 { CALL , "call",picGenericOne , NULL },
80 { PCALL , "pcall",picGenericOne , NULL },
81 { FUNCTION , "proc", picGenericOne , NULL },
82 { ENDFUNCTION ,"eproc", picGenericOne , NULL },
83 { RETURN , "ret", picGenericOne , NULL },
84 { '+' , "+" , picGeneric , NULL },
85 { '-' , "-" , picGeneric , NULL },
86 { '*' , "*" , picGeneric , NULL },
87 { '/' , "/" , picGeneric , NULL },
88 { '%' , "%" , picGeneric , NULL },
89 { '>' , ">" , picGeneric , NULL },
90 { '<' , "<" , picGeneric , NULL },
91 { LE_OP , "<=" , picGeneric , NULL },
92 { GE_OP , ">=" , picGeneric , NULL },
93 { EQ_OP , "==" , picGeneric , NULL },
94 { NE_OP , "!=" , picGeneric , NULL },
95 { AND_OP , "&&" , picGeneric , NULL },
96 { OR_OP , "||" , picGeneric , NULL },
97 { '^' , "^" , picGeneric , NULL },
98 { '|' , "|" , picGeneric , NULL },
99 { BITWISEAND , "&" , picGeneric , NULL },
100 { LEFT_OP , "<<" , picGeneric , NULL },
101 { RIGHT_OP , ">>" , picGeneric , NULL },
102 { GET_VALUE_AT_ADDRESS, "@" , picGetValueAtAddr, NULL },
103 { ADDRESS_OF , "&" , picAddrOf , NULL },
104 { CAST , "<>" , picCast , NULL },
105 { '=' , ":=" , picAssign , NULL },
106 { LABEL , "" , picLabel , NULL },
107 { GOTO , "" , picGoto , NULL },
108 { JUMPTABLE ,"jtab" , picJumpTable , NULL },
109 { IFX , "if" , picIfx , NULL },
110 { INLINEASM , "" , picInline , NULL },
111 { RECEIVE , "recv", picReceive , NULL },
112 { SEND , "send", picGenericOne , NULL }
116 /*-----------------------------------------------------------------*/
117 /* operandName - returns the name of the operand */
118 /*-----------------------------------------------------------------*/
119 int printOperand (operand *op, FILE *file)
134 opetype = getSpec (operandType(op));
135 if (SPEC_NOUN(opetype) == V_FLOAT)
136 fprintf (file,"%g {", SPEC_CVAL(opetype).v_float);
138 fprintf (file,"0x%x {",(int) floatFromVal(op->operand.valOperand));
139 printTypeChain(operandType(op),file);
146 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}" ,*/
147 (OP_SYMBOL(op)->rname[0] ? OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name),
149 OP_LIVEFROM(op),OP_LIVETO(op),
150 OP_SYMBOL(op)->stack,
151 op->isaddr, OP_SYMBOL(op)->isreqv,OP_SYMBOL(op)->remat
153 /* OP_SYMBOL(op)->allocreq,OP_SYMBOL(op)->remat, */
154 /* OP_SYMBOL(op)->ruonly, */
155 /* OP_SYMBOL(op)->isptr,op->isaddr,OP_SYMBOL(op)->used, */
156 /* OP_SYMBOL(op)->isind, */
157 /* OP_SYMBOL(op)->accuse, op->key, OP_SYMBOL(op)->key */
160 fprintf(file,"{"); printTypeChain(operandType(op),file);
161 if (SPIL_LOC(op) && IS_ITEMP(op))
162 fprintf(file,"}{ sir@ %s",SPIL_LOC(op)->rname);
167 /* if assigned to registers */
168 if (OP_SYMBOL(op)->nRegs) {
169 if (OP_SYMBOL(op)->isspilt) {
170 if (!OP_SYMBOL(op)->remat)
171 if (OP_SYMBOL(op)->usl.spillLoc)
172 fprintf(file,"[%s]",(OP_SYMBOL(op)->usl.spillLoc->rname[0] ?
173 OP_SYMBOL(op)->usl.spillLoc->rname :
174 OP_SYMBOL(op)->usl.spillLoc->name));
176 fprintf(file,"[err]");
178 fprintf(file,"[remat]");
183 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
184 fprintf(file,"%s ", port->getRegName(OP_SYMBOL(op)->regs[i]));
189 fprintf(file,"%s",(OP_SYMBOL(op)->rname[0] ?
190 OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name));
191 /* if assigned to registers */
192 if (OP_SYMBOL(op)->nRegs && !OP_SYMBOL(op)->isspilt) {
195 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
196 fprintf(file,"%s ",(OP_SYMBOL(op)->regs[i] ?
197 OP_SYMBOL(op)->regs[i]->name :
206 printTypeChain(op->operand.typeOperand,file);
217 /*-----------------------------------------------------------------*/
218 /* print functions */
219 /*-----------------------------------------------------------------*/
220 PRINTFUNC(picGetValueAtAddr)
223 printOperand (IC_RESULT(ic),of);
226 printOperand (IC_LEFT(ic), of);
232 PRINTFUNC(picSetValueAtAddr)
236 printOperand(IC_LEFT(ic),of);
238 printOperand(IC_RIGHT(ic),of);
245 printOperand(IC_RESULT(ic),of);
246 if (IS_ITEMP(IC_LEFT(ic)))
250 printOperand(IC_LEFT(ic),of);
252 if (IS_ITEMP(IC_LEFT(ic)))
253 fprintf(of," offsetAdd ");
256 printOperand(IC_RIGHT(ic),of);
258 if (IS_ITEMP(IC_LEFT(ic)))
264 PRINTFUNC(picJumpTable)
269 fprintf(of,"%s\t",s);
270 printOperand(IC_JTCOND(ic),of);
272 for ( sym = setFirstItem(IC_JTLABELS(ic)); sym;
273 sym = setNextItem(IC_JTLABELS(ic)))
274 fprintf(of,"\t\t\t%s\n",sym->name);
277 PRINTFUNC(picGeneric)
280 printOperand(IC_RESULT(ic),of);
282 printOperand(IC_LEFT(ic),of);
283 fprintf(of," %s ",s);
284 printOperand(IC_RIGHT(ic),of);
288 PRINTFUNC(picGenericOne)
291 if ( IC_RESULT(ic) ) {
292 printOperand(IC_RESULT(ic),of);
297 fprintf (of,"%s ",s);
298 printOperand(IC_LEFT(ic),of);
301 if (! IC_RESULT(ic) && !IC_LEFT(ic))
310 printOperand(IC_RESULT(ic),of);
312 printOperand(IC_LEFT(ic),of);
313 printOperand(IC_RIGHT(ic),of);
322 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
325 printOperand(IC_RESULT(ic),of);
327 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
330 fprintf(of," %s ", s);
331 printOperand (IC_RIGHT(ic),of);
338 fprintf(of," %s($%d) :\n",IC_LABEL(ic)->name,IC_LABEL(ic)->key);
344 fprintf (of," goto %s($%d)\n", IC_LABEL(ic)->name,IC_LABEL(ic)->key);
351 printOperand(IC_COND(ic),of);
354 fprintf (of," == 0 goto %s($%d)\n",IC_FALSE(ic)->name,IC_FALSE(ic)->key);
356 fprintf (of," != 0 goto %s($%d)\n",IC_TRUE(ic)->name,IC_TRUE(ic)->key);
358 fprintf (of,"\tzzgoto %s\n",IC_FALSE(ic)->name);
364 fprintf(of,"%s",IC_INLINE(ic));
367 PRINTFUNC(picReceive)
369 printOperand(IC_RESULT(ic),of);
370 fprintf(of," = %s ",s);
371 printOperand(IC_LEFT(ic),of);
375 /*-----------------------------------------------------------------*/
376 /* piCode - prints one iCode */
377 /*-----------------------------------------------------------------*/
378 int piCode (void *item, FILE *of)
386 icTab = getTableEntry(ic->op) ;
387 fprintf(stdout,"%s(%d:%d:%d:%d:%d)\t",
388 ic->filename,ic->lineno,
389 ic->seq,ic->key,ic->depth,ic->supportRtn);
390 icTab->iCodePrint(of,ic,icTab->printName);
394 /*-----------------------------------------------------------------*/
395 /* printiCChain - prints intermediate code for humans */
396 /*-----------------------------------------------------------------*/
397 void printiCChain (iCode *icChain, FILE *of)
404 for ( loop = icChain ; loop ; loop = loop->next ) {
405 if ((icTab = getTableEntry (loop->op ))) {
406 fprintf(of,"%s(%d:%d:%d:%d:%d)\t",
407 loop->filename,loop->lineno,
408 loop->seq,loop->key,loop->depth,loop->supportRtn);
410 icTab->iCodePrint (of,loop,icTab->printName);
416 /*-----------------------------------------------------------------*/
417 /* newOperand - allocate, init & return a new iCode */
418 /*-----------------------------------------------------------------*/
419 operand *newOperand ()
423 ALLOC(op,sizeof(operand));
429 /*-----------------------------------------------------------------*/
430 /* newiCode - create and return a new iCode entry initialised */
431 /*-----------------------------------------------------------------*/
432 iCode *newiCode (int op, operand *left, operand *right)
436 ALLOC(ic,sizeof(iCode));
438 ic->lineno = lineno ;
439 ic->filename= filename ;
441 ic->level = scopeLevel;
443 ic->key= iCodeKey++ ;
450 /*-----------------------------------------------------------------*/
451 /* newiCode for conditional statements */
452 /*-----------------------------------------------------------------*/
453 iCode *newiCodeCondition (operand *condition,
459 ic = newiCode(IFX,NULL,NULL);
460 IC_COND(ic) = condition ;
461 IC_TRUE(ic) = trueLabel ;
462 IC_FALSE(ic) = falseLabel;
466 /*-----------------------------------------------------------------*/
467 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
468 /*-----------------------------------------------------------------*/
469 iCode *newiCodeLabelGoto (int op, symbol *label)
473 ic = newiCode(op,NULL,NULL);
475 ic->argLabel.label = label ;
477 IC_RIGHT(ic) = NULL ;
478 IC_RESULT(ic) = NULL ;
482 /*-----------------------------------------------------------------*/
483 /* newiTemp - allocate & return a newItemp Variable */
484 /*-----------------------------------------------------------------*/
485 symbol *newiTemp (char *s)
490 sprintf(buffer,"%s",s);
492 sprintf (buffer,"iTemp%d",iTempNum++);
493 itmp = newSymbol (buffer,1);
494 strcpy(itmp->rname,itmp->name);
500 /*-----------------------------------------------------------------*/
501 /* newiTempLabel - creates a temp variable label */
502 /*-----------------------------------------------------------------*/
503 symbol *newiTempLabel (char *s)
507 /* check if this alredy exists */
508 if (s && (itmplbl = findSym(LabelTab, NULL, s)))
512 itmplbl = newSymbol(s,1);
514 sprintf(buffer,"iTempLbl%d",iTempLblNum++);
515 itmplbl = newSymbol(buffer,1);
520 itmplbl->key = labelKey++ ;
521 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
525 /*-----------------------------------------------------------------*/
526 /* newiTempPreheaderLabel - creates a new preheader label */
527 /*-----------------------------------------------------------------*/
528 symbol *newiTempPreheaderLabel()
532 sprintf(buffer,"preHeaderLbl%d",iTempLblNum++);
533 itmplbl = newSymbol(buffer,1);
537 itmplbl->key = labelKey++ ;
538 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
543 /*-----------------------------------------------------------------*/
544 /* initiCode - initialises some iCode related stuff */
545 /*-----------------------------------------------------------------*/
551 /*-----------------------------------------------------------------*/
552 /* copyiCode - make a copy of the iCode given */
553 /*-----------------------------------------------------------------*/
554 iCode *copyiCode (iCode *ic)
556 iCode *nic = newiCode(ic->op,NULL,NULL);
558 nic->lineno = ic->lineno ;
559 nic->filename= ic->filename ;
560 nic->block = ic->block;
561 nic->level = ic->level;
563 /* deal with the special cases first */
566 IC_COND(nic) = operandFromOperand(IC_COND(ic));
567 IC_TRUE(nic) = IC_TRUE(ic);
568 IC_FALSE(nic)= IC_FALSE(ic);
572 IC_JTCOND(nic) = operandFromOperand(IC_JTCOND(ic));
573 IC_JTLABELS(nic) = IC_JTLABELS(ic);
578 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
579 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
580 IC_ARGS(nic) = IC_ARGS(ic);
584 IC_INLINE(nic) = IC_INLINE(ic);
588 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
589 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
590 IC_RIGHT(nic)= operandFromOperand(IC_RIGHT(ic));
596 /*-----------------------------------------------------------------*/
597 /* getTableEntry - gets the table entry for the given operator */
598 /*-----------------------------------------------------------------*/
599 iCodeTable *getTableEntry (int oper )
603 for ( i = 0 ; i < (sizeof(codeTable)/sizeof(iCodeTable)); i++ )
604 if (oper == codeTable[i].icode)
605 return &codeTable[i] ;
610 /*-----------------------------------------------------------------*/
611 /* newiTempOperand - new intermediate temp operand */
612 /*-----------------------------------------------------------------*/
613 operand *newiTempOperand (link *type, char throwType)
616 operand *op = newOperand();
620 itmp = newiTemp(NULL);
622 etype = getSpec(type);
624 if (IS_LITERAL(etype) )
627 /* copy the type information */
629 itmp->etype = getSpec (itmp->type = (throwType ? type :
630 copyLinkChain(type)));
631 if (IS_LITERAL(itmp->etype)) {
632 SPEC_SCLS(itmp->etype) = S_REGISTER ;
633 SPEC_OCLS(itmp->etype) = reg;
636 op->operand.symOperand = itmp;
637 op->key = itmp->key = ++operandKey ;
641 /*-----------------------------------------------------------------*/
642 /* operandType - returns the type chain for an operand */
643 /*-----------------------------------------------------------------*/
644 link *operandType (operand *op)
646 /* depending on type of operand */
650 return op->operand.valOperand->type ;
653 return op->operand.symOperand->type ;
656 return op->operand.typeOperand ;
659 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
660 " operand type not known ");
661 assert (0) ; /* should never come here */
662 /* Just to keep the compiler happy */
666 /*-----------------------------------------------------------------*/
667 /* isParamterToCall - will return 1 if op is a parameter to args */
668 /*-----------------------------------------------------------------*/
669 int isParameterToCall (value *args, operand *op)
675 isSymbolEqual(op->operand.symOperand,tval->sym))
682 /*-----------------------------------------------------------------*/
683 /* isOperandGlobal - return 1 if operand is a global variable */
684 /*-----------------------------------------------------------------*/
685 int isOperandGlobal ( operand *op )
693 if (op->type == SYMBOL &&
694 (op->operand.symOperand->level == 0 ||
695 IS_STATIC(op->operand.symOperand->etype) ||
696 IS_EXTERN(op->operand.symOperand->etype))
703 /*-----------------------------------------------------------------*/
704 /* isOperandVolatile - return 1 if the operand is volatile */
705 /*-----------------------------------------------------------------*/
706 int isOperandVolatile ( operand *op , bool chkTemp)
711 if (IS_ITEMP(op) && !chkTemp)
714 opetype = getSpec(optype = operandType(op));
716 if (IS_PTR(optype) && DCL_PTR_VOLATILE(optype))
719 if (IS_VOLATILE(opetype))
724 /*-----------------------------------------------------------------*/
725 /* isOperandLiteral - returns 1 if an operand contains a literal */
726 /*-----------------------------------------------------------------*/
727 int isOperandLiteral ( operand *op )
734 opetype = getSpec (operandType(op));
736 if (IS_LITERAL(opetype))
741 /*-----------------------------------------------------------------*/
742 /* isOperandInFarSpace - will return true if operand is in farSpace*/
743 /*-----------------------------------------------------------------*/
744 bool isOperandInFarSpace (operand *op)
754 if (!IS_TRUE_SYMOP(op)) {
756 etype = SPIL_LOC(op)->etype;
761 etype = getSpec(operandType(op));
762 return (IN_FARSPACE(SPEC_OCLS(etype)) ? TRUE : FALSE);
765 /*-----------------------------------------------------------------*/
766 /* operandLitValue - literal value of an operand */
767 /*-----------------------------------------------------------------*/
768 double operandLitValue ( operand *op )
770 assert(isOperandLiteral(op));
772 return floatFromVal(op->operand.valOperand);
775 /*-----------------------------------------------------------------*/
776 /* operandOperation - perforoms operations on operands */
777 /*-----------------------------------------------------------------*/
778 operand *operandOperation (operand *left,operand *right,
781 operand *retval = (operand *)0;
783 assert(isOperandLiteral(left));
785 assert(isOperandLiteral(right));
789 retval = operandFromValue (valCastLiteral(type,
790 operandLitValue(left) +
791 operandLitValue(right)));
794 retval = operandFromValue(valCastLiteral(type,
795 operandLitValue(left) -
796 operandLitValue(right)));
799 retval = operandFromValue(valCastLiteral(type,
800 operandLitValue(left) *
801 operandLitValue(right)));
804 if ((unsigned long) operandLitValue(right) == 0){
805 werror(E_DIVIDE_BY_ZERO);
810 retval = operandFromValue (valCastLiteral(type,
811 operandLitValue(left) /
812 operandLitValue(right)));
815 if ((unsigned long) operandLitValue(right) == 0){
816 werror(E_DIVIDE_BY_ZERO);
820 retval = operandFromLit ((unsigned long) operandLitValue(left) %
821 (unsigned long) operandLitValue(right));
824 retval = operandFromLit ((unsigned long) operandLitValue(left) <<
825 (unsigned long) operandLitValue(right));
828 retval = operandFromLit ((unsigned long) operandLitValue(left) >>
829 (unsigned long) operandLitValue(right));
832 retval = operandFromLit (operandLitValue(left) ==
833 operandLitValue(right));
836 retval = operandFromLit (operandLitValue(left) <
837 operandLitValue(right));
840 retval = operandFromLit (operandLitValue(left) <=
841 operandLitValue(right));
844 retval = operandFromLit (operandLitValue(left) !=
845 operandLitValue(right));
848 retval = operandFromLit (operandLitValue(left) >
849 operandLitValue(right));
852 retval = operandFromLit (operandLitValue(left) >=
853 operandLitValue(right));
856 retval = operandFromLit ((unsigned long) operandLitValue(left) &
857 (unsigned long) operandLitValue(right));
860 retval = operandFromLit ((unsigned long) operandLitValue(left) |
861 (unsigned long) operandLitValue(right));
864 retval = operandFromLit ((unsigned long) operandLitValue(left) ^
865 (unsigned long) operandLitValue(right));
868 retval = operandFromLit (operandLitValue(left) &&
869 operandLitValue(right));
872 retval = operandFromLit (operandLitValue(left) ||
873 operandLitValue(right));
877 long i = operandLitValue(left);
879 retval = operandFromLit ((i >> (getSize(operandType(left))*8 - 1)) |
885 long i = operandLitValue(left);
887 retval = operandFromLit ((i << (getSize(operandType(left))*8 - 1)) |
893 retval = operandFromLit(-1 * operandLitValue(left));
897 retval = operandFromLit(~ ((long) operandLitValue(left)));
901 retval = operandFromLit(! operandLitValue(left));
905 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
906 " operandOperation invalid operator ");
914 /*-----------------------------------------------------------------*/
915 /* isOperandEqual - compares two operand & return 1 if they r = */
916 /*-----------------------------------------------------------------*/
917 int isOperandEqual (operand *left, operand *right)
919 /* if the pointers are equal then they are equal */
923 /* if either of them null then false */
924 if ( !left || !right)
927 if (left->type != right->type)
930 if (IS_SYMOP(left) && IS_SYMOP(right))
931 return left->key == right->key ;
933 /* if types are the same */
934 switch (left->type) {
936 return isSymbolEqual(left->operand.symOperand,
937 right->operand.symOperand);
939 return (floatFromVal(left->operand.valOperand) ==
940 floatFromVal(right->operand.valOperand));
942 if (checkType(left->operand.typeOperand,
943 right->operand.typeOperand) == 1)
950 /*-----------------------------------------------------------------*/
951 /* isiCodeEqual - comapres two iCodes are returns true if yes */
952 /*-----------------------------------------------------------------*/
953 int isiCodeEqual (iCode *left, iCode *right)
955 /* if the same pointer */
959 /* if either of them null */
963 /* if operand are the same */
964 if ( left->op == right->op ) {
966 /* compare all the elements depending on type */
967 if (left->op != IFX ) {
968 if (!isOperandEqual(IC_LEFT(left),IC_LEFT(right)))
970 if (!isOperandEqual(IC_RIGHT(left),IC_RIGHT(right)))
974 if (!isOperandEqual(IC_COND(left),IC_COND(right)))
976 if (!isSymbolEqual (IC_TRUE(left),IC_TRUE(right)))
978 if (!isSymbolEqual(IC_FALSE(left),IC_FALSE(right)))
986 /*-----------------------------------------------------------------*/
987 /* newiTempFromOp - create a temp Operand with same attributes */
988 /*-----------------------------------------------------------------*/
989 operand *newiTempFromOp (operand *op)
999 nop = newiTempOperand(operandType(op),TRUE);
1000 nop->isaddr = op->isaddr ;
1001 nop->isvolatile = op->isvolatile ;
1002 nop->isGlobal = op->isGlobal ;
1003 nop->isLiteral= op->isLiteral ;
1004 nop->noSpilLoc= op->noSpilLoc;
1005 nop->usesDefs = op->usesDefs;
1006 nop->isParm = op->isParm;
1007 nop->parmBytes = op->parmBytes;
1011 /*-----------------------------------------------------------------*/
1012 /* operand from operand - creates an operand holder for the type */
1013 /*-----------------------------------------------------------------*/
1014 operand *operandFromOperand (operand *op)
1021 nop->type = op->type;
1022 nop->isaddr = op->isaddr ;
1023 nop->key = op->key ;
1024 nop->isvolatile = op->isvolatile ;
1025 nop->isGlobal = op->isGlobal ;
1026 nop->isLiteral= op->isLiteral ;
1027 nop->noSpilLoc= op->noSpilLoc;
1028 nop->usesDefs = op->usesDefs;
1029 nop->isParm = op->isParm;
1030 nop->parmBytes = op->parmBytes;
1032 switch (nop->type) {
1034 nop->operand.symOperand = op->operand.symOperand ;
1037 nop->operand.valOperand = op->operand.valOperand;
1040 nop->operand.typeOperand = op->operand.typeOperand ;
1047 /*-----------------------------------------------------------------*/
1048 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1049 /*-----------------------------------------------------------------*/
1050 operand *opFromOpWithDU (operand *op, bitVect *defs, bitVect *uses)
1052 operand *nop = operandFromOperand(op);
1054 if (nop->type == SYMBOL) {
1055 OP_SYMBOL(nop)->defs = bitVectCopy(defs);
1056 OP_SYMBOL(nop)->uses = bitVectCopy(uses);
1062 /*-----------------------------------------------------------------*/
1063 /* operandFromSymbol - creates an operand from a symbol */
1064 /*-----------------------------------------------------------------*/
1065 operand *operandFromSymbol (symbol *sym)
1070 /* if the symbol's type is a literal */
1071 /* then it is an enumerator type */
1072 if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype))
1073 return operandFromValue (valFromType(sym->etype));
1076 sym->key = ++operandKey ;
1078 /* if this an implicit variable, means struct/union */
1079 /* member so just return it */
1080 if (sym->implicit || IS_FUNC(sym->type)) {
1083 op->operand.symOperand = sym;
1084 op->key = sym->key ;
1085 op->isvolatile = isOperandVolatile(op,TRUE);
1086 op->isGlobal = isOperandGlobal(op);
1087 op->parmBytes = sym->argStack;
1091 /* under the following conditions create a
1092 register equivalent for a local symbol */
1093 if (!IS_AGGREGATE(sym->type) && /* not an aggregate */
1094 !IS_FUNC(sym->type) && /* not a function */
1095 !sym->_isparm && /* not a parameter */
1096 sym->level && /* is a local variable */
1097 !sym->addrtaken && /* whose address has not been taken */
1098 !sym->reqv && /* does not already have a register euivalence */
1099 !IS_VOLATILE(sym->etype) && /* not declared as volatile */
1100 !IS_STATIC(sym->etype) && /* and not declared static */
1101 !sym->islbl && /* not a label */
1102 !IN_FARSPACE(SPEC_OCLS(sym->etype)) && /* not in far space */
1103 !IS_BITVAR(sym->etype) /* not a bit variable */
1106 /* we will use it after all optimizations
1107 and before liveRange calculation */
1108 sym->reqv = newiTempOperand(sym->type,0);
1109 sym->reqv->key = sym->key ;
1110 OP_SYMBOL(sym->reqv)->key = sym->key;
1111 OP_SYMBOL(sym->reqv)->isreqv = 1;
1112 OP_SYMBOL(sym->reqv)->islocal = 1;
1113 SPIL_LOC(sym->reqv) = sym;
1116 if (!IS_AGGREGATE(sym->type)) {
1119 op->operand.symOperand = sym;
1122 op->isvolatile = isOperandVolatile(op,TRUE);
1123 op->isGlobal = isOperandGlobal(op);
1124 op->isPtr = IS_PTR(operandType(op));
1125 op->isParm = sym->_isparm ;
1130 /* itemp = &[_symbol] */
1132 ic = newiCode(ADDRESS_OF,newOperand(),NULL);
1133 IC_LEFT(ic)->type = SYMBOL ;
1134 IC_LEFT(ic)->operand.symOperand = sym ;
1135 IC_LEFT(ic)->key = sym->key;
1136 (IC_LEFT(ic))->isvolatile = isOperandVolatile(IC_LEFT(ic),TRUE);
1137 (IC_LEFT(ic))->isGlobal = isOperandGlobal(IC_LEFT(ic));
1138 IC_LEFT(ic)->isPtr = IS_PTR(operandType(IC_LEFT(ic)));
1141 IC_RESULT(ic) = newiTempOperand(sym->type,0);
1142 if (IS_ARRAY(sym->type)) {
1143 IC_RESULT(ic) = geniCodeArray2Ptr (IC_RESULT(ic));
1144 IC_RESULT(ic)->isaddr = 0;
1146 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(sym->type));
1148 IC_RESULT(ic)->operand.symOperand->args = sym->args;
1152 return IC_RESULT(ic) ;
1155 /*-----------------------------------------------------------------*/
1156 /* operandFromValue - creates an operand from value */
1157 /*-----------------------------------------------------------------*/
1158 operand *operandFromValue (value *val)
1162 /* if this is a symbol then do the symbol thing */
1164 return operandFromSymbol (val->sym);
1166 /* this is not a symbol */
1169 op->operand.valOperand = val ;
1170 op->isLiteral = isOperandLiteral(op);
1174 /*-----------------------------------------------------------------*/
1175 /* operandFromLink - operand from typeChain */
1176 /*-----------------------------------------------------------------*/
1177 operand *operandFromLink (link *type)
1181 /* operand from link */
1187 op->operand.typeOperand = copyLinkChain(type);
1191 /*-----------------------------------------------------------------*/
1192 /* operandFromLit - makes an operand from a literal value */
1193 /*-----------------------------------------------------------------*/
1194 operand *operandFromLit ( float i)
1196 return operandFromValue (valueFromLit (i));
1199 /*-----------------------------------------------------------------*/
1200 /* operandFromAst - creates an operand from an ast */
1201 /*-----------------------------------------------------------------*/
1202 operand *operandFromAst ( ast *tree )
1208 /* depending on type do */
1209 switch (tree->type ) {
1211 return ast2iCode (tree) ;
1215 return operandFromValue(tree->opval.val) ;
1219 return operandFromLink (tree->opval.lnk) ;
1223 /* Just to keep the comiler happy */
1224 return (operand *)0;
1227 /*-----------------------------------------------------------------*/
1228 /* setOperandType - sets the operand's type to the given type */
1229 /*-----------------------------------------------------------------*/
1230 void setOperandType (operand *op, link *type)
1232 /* depending on the type of operand */
1236 op->operand.valOperand->etype =
1237 getSpec( op->operand.valOperand->type =
1238 copyLinkChain (type )) ;
1242 if (op->operand.symOperand->isitmp )
1243 op->operand.symOperand->etype =
1244 getSpec( op->operand.symOperand->type =
1245 copyLinkChain (type )) ;
1247 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
1248 "attempt to modify type of source");
1252 op->operand.typeOperand = copyLinkChain (type);
1258 /*-----------------------------------------------------------------*/
1259 /* geniCodeValueAtAddress - generate intermeditate code for value */
1261 /*-----------------------------------------------------------------*/
1262 operand *geniCodeRValue (operand *op, bool force)
1265 link *type = operandType(op);
1266 link *etype= getSpec(type);
1268 /* if this is an array & already */
1269 /* an address then return this */
1270 if (IS_AGGREGATE(type) ||
1271 (IS_PTR(type) && !force && !op->isaddr))
1272 return operandFromOperand(op);
1274 /* if this is not an address then must be */
1275 /* rvalue already so return this one */
1279 /* if this is not a temp symbol then */
1280 if (!IS_ITEMP(op) &&
1282 !IN_FARSPACE(SPEC_OCLS(etype))) {
1283 op = operandFromOperand(op);
1288 if (IS_SPEC(type) &&
1289 IS_TRUE_SYMOP(op) &&
1290 !IN_FARSPACE(SPEC_OCLS(etype))) {
1291 op = operandFromOperand(op);
1296 ic = newiCode(GET_VALUE_AT_ADDRESS,op,NULL);
1297 if (IS_PTR(type) && op->isaddr && force)
1300 type = copyLinkChain(type);
1302 IC_RESULT(ic) = newiTempOperand (type,1);
1303 IC_RESULT(ic)->isaddr = 0;
1305 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1307 /* if the right is a symbol */
1308 if (op->type == SYMBOL)
1309 IC_RESULT(ic)->operand.symOperand->args =
1310 op->operand.symOperand->args ;
1313 return IC_RESULT(ic) ;
1316 /*-----------------------------------------------------------------*/
1317 /* geniCodeCast - changes the value from one type to another */
1318 /*-----------------------------------------------------------------*/
1319 operand *geniCodeCast (link *type, operand *op, bool implicit)
1323 link *opetype = getSpec(optype = operandType(op));
1326 /* one of them has size zero then error */
1327 if (IS_VOID(optype)) {
1328 werror(E_CAST_ZERO);
1332 /* if the operand is already the desired type then do nothing */
1333 if ( checkType (type,optype) == 1)
1336 /* if this is a literal then just change the type & return */
1337 if (IS_LITERAL(opetype) && !IS_PTR(type) && !IS_PTR(optype))
1338 return operandFromValue(valCastLiteral(type,
1339 operandLitValue(op)));
1341 /* if casting to some pointer type &&
1342 the destination is not a generic pointer
1343 then give a warning : (only for implicit casts)*/
1344 if (IS_PTR(optype) && implicit &&
1345 (DCL_TYPE(optype) != DCL_TYPE(type)) &&
1347 werror(E_INCOMPAT_CAST);
1348 werror(E_CONTINUE,"from type '");
1349 printTypeChain(optype,stderr);fprintf(stderr,"' to type '");
1350 printTypeChain(type,stderr);fprintf(stderr,"'\n");
1353 /* if they are the same size create an assignment */
1354 if (getSize(type) == getSize(optype) &&
1355 !IS_BITFIELD(type) &&
1357 !IS_FLOAT(optype) &&
1358 ((IS_SPEC(type) && IS_SPEC(optype)) ||
1359 (!IS_SPEC(type) && !IS_SPEC(optype)))) {
1361 ic = newiCode('=',NULL,op);
1362 IC_RESULT(ic) = newiTempOperand(type,0);
1363 SPIL_LOC(IC_RESULT(ic)) =
1364 (IS_TRUE_SYMOP(op) ? OP_SYMBOL(op) : NULL);
1365 IC_RESULT(ic)->isaddr = 0;
1367 ic = newiCode(CAST,operandFromLink(type),
1368 geniCodeRValue(op,FALSE));
1370 IC_RESULT(ic)= newiTempOperand(type,0);
1373 /* preserve the storage class & output class */
1374 /* of the original variable */
1375 restype = getSpec(operandType(IC_RESULT(ic)));
1376 SPEC_SCLS(restype) = SPEC_SCLS(opetype);
1377 SPEC_OCLS(restype) = SPEC_OCLS(opetype);
1380 return IC_RESULT(ic) ;
1383 /*-----------------------------------------------------------------*/
1384 /* geniCodeLabel - will create a Label */
1385 /*-----------------------------------------------------------------*/
1386 void geniCodeLabel (symbol *label)
1390 ic = newiCodeLabelGoto(LABEL,label);
1394 /*-----------------------------------------------------------------*/
1395 /* geniCodeGoto - will create a Goto */
1396 /*-----------------------------------------------------------------*/
1397 void geniCodeGoto (symbol *label)
1401 ic = newiCodeLabelGoto(GOTO,label);
1405 /*-----------------------------------------------------------------*/
1406 /* geniCodeMultiply - gen intermediate code for multiplication */
1407 /*-----------------------------------------------------------------*/
1408 operand *geniCodeMultiply (operand *left, operand *right)
1415 /* if they are both literal then we know the result */
1416 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1417 return operandFromValue (valMult(left->operand.valOperand,
1418 right->operand.valOperand));
1420 resType = computeType (ltype,rtype) ;
1421 left = geniCodeCast(resType,left,TRUE);
1422 right= geniCodeCast(resType,right,TRUE);
1424 /* if the right is a literal & power of 2 */
1425 /* then make it a left shift */
1426 if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
1427 (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand))))
1428 ic = newiCode(LEFT_OP, left,operandFromLit(p2)); /* left shift */
1430 ic = newiCode('*',left,right); /* normal multiplication */
1431 /* if the size left or right > 1 then support routine */
1432 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1436 IC_RESULT(ic) = newiTempOperand(resType,1);
1439 return IC_RESULT(ic) ;
1442 /*-----------------------------------------------------------------*/
1443 /* geniCodeDivision - gen intermediate code for division */
1444 /*-----------------------------------------------------------------*/
1445 operand *geniCodeDivision (operand *left, operand *right)
1450 link *rtype = operandType(right);
1451 link *retype= getSpec(rtype);
1452 link *ltype = operandType(left);
1453 link *letype= getSpec(ltype);
1455 resType = computeType (ltype,rtype) ;
1456 left = geniCodeCast(resType,left,TRUE);
1457 right= geniCodeCast(resType,right,TRUE);
1459 /* if the right is a literal & power of 2 */
1460 /* then make it a right shift */
1461 if (IS_LITERAL(retype) &&
1462 !IS_FLOAT(letype) &&
1463 (p2 = powof2 ((unsigned long)
1464 floatFromVal(right->operand.valOperand))))
1465 ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
1467 ic = newiCode('/',left,right); /* normal division */
1468 /* if the size left or right > 1 then support routine */
1469 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1472 IC_RESULT(ic) = newiTempOperand(resType,0);
1475 return IC_RESULT(ic) ;
1477 /*-----------------------------------------------------------------*/
1478 /* geniCodeModulus - gen intermediate code for modulus */
1479 /*-----------------------------------------------------------------*/
1480 operand *geniCodeModulus (operand *left, operand *right)
1486 /* if they are both literal then we know the result */
1487 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1488 return operandFromValue (valMod(left->operand.valOperand,
1489 right->operand.valOperand));
1491 resType = computeType (ltype,rtype) ;
1492 left = geniCodeCast(resType,left,TRUE);
1493 right= geniCodeCast(resType,right,TRUE);
1495 /* now they are the same size */
1496 ic = newiCode('%',left,right);
1498 /* if the size left or right > 1 then support routine */
1499 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1501 IC_RESULT(ic) = newiTempOperand(resType,0);
1504 return IC_RESULT(ic) ;
1507 /*-----------------------------------------------------------------*/
1508 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1509 /*-----------------------------------------------------------------*/
1510 operand *geniCodePtrPtrSubtract (operand *left, operand *right)
1516 /* if they are both literals then */
1517 if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
1518 result = operandFromValue (valMinus(left->operand.valOperand,
1519 right->operand.valOperand));
1523 ic = newiCode('-',left,right);
1525 IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
1529 return geniCodeDivision (result,
1530 operandFromLit(getSize(ltype->next)));
1533 /*-----------------------------------------------------------------*/
1534 /* geniCodeSubtract - generates code for subtraction */
1535 /*-----------------------------------------------------------------*/
1536 operand *geniCodeSubtract (operand *left, operand *right)
1543 /* if they both pointers then */
1544 if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
1545 (IS_PTR(rtype) || IS_ARRAY(rtype)))
1546 return geniCodePtrPtrSubtract (left,right);
1548 /* if they are both literal then we know the result */
1549 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1550 return operandFromValue (valMinus(left->operand.valOperand,
1551 right->operand.valOperand));
1553 /* if left is an array or pointer */
1554 if ( IS_PTR(ltype) || IS_ARRAY(ltype) ) {
1555 isarray = left->isaddr ;
1556 right = geniCodeMultiply (right,
1557 operandFromLit(getSize(ltype->next)));
1558 resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
1560 else { /* make them the same size */
1561 resType = computeType (ltype,rtype) ;
1562 left = geniCodeCast(resType,left,TRUE);
1563 right= geniCodeCast(resType,right,TRUE);
1566 ic = newiCode('-',left,right);
1568 IC_RESULT(ic)= newiTempOperand(resType,1);
1569 IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
1571 /* if left or right is a float */
1572 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1576 return IC_RESULT(ic) ;
1579 /*-----------------------------------------------------------------*/
1580 /* geniCodeAdd - generates iCode for addition */
1581 /*-----------------------------------------------------------------*/
1582 operand *geniCodeAdd (operand *left, operand *right )
1590 /* if left is an array then array access */
1591 if (IS_ARRAY(ltype))
1592 return geniCodeArray (left,right);
1594 /* if the right side is LITERAL zero */
1595 /* return the left side */
1596 if (IS_LITERAL(retype) && !floatFromVal(valFromType(retype)))
1599 /* if left is literal zero return right */
1600 if (IS_LITERAL(letype) && !floatFromVal(valFromType(letype)))
1603 /* if left is an array or pointer then size */
1604 if (IS_PTR(ltype)) {
1606 isarray = left->isaddr;
1608 operandFromLit(getSize(ltype->next));
1609 right = geniCodeMultiply (right ,size);
1610 resType = copyLinkChain(ltype);
1612 else { /* make them the same size */
1613 resType = computeType (ltype,rtype) ;
1614 left = geniCodeCast(resType,left,TRUE);
1615 right= geniCodeCast(resType,right,TRUE);
1618 /* if they are both literals then we know */
1619 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1620 return operandFromValue (valPlus(valFromType(letype),
1621 valFromType(retype)));
1623 ic = newiCode('+',left,right);
1625 IC_RESULT(ic) = newiTempOperand(resType,1);
1626 IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
1628 /* if left or right is a float then support
1630 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1635 return IC_RESULT(ic) ;
1639 /*-----------------------------------------------------------------*/
1640 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1641 /*-----------------------------------------------------------------*/
1642 link *aggrToPtr ( link *type, bool force)
1648 if (IS_PTR(type) && !force)
1651 etype = getSpec(type);
1655 /* if the output class is generic */
1656 if ((DCL_TYPE(ptype) = PTR_TYPE(SPEC_OCLS(etype))) == CPOINTER)
1657 DCL_PTR_CONST(ptype) = 1;
1659 /* if (SPEC_OCLS(etype) == generic) */
1660 /* DCL_TYPE(ptype) = GPOINTER; */
1662 /* if (SPEC_OCLS(etype)->codesp ) { */
1663 /* DCL_TYPE(ptype) = CPOINTER ; */
1664 /* DCL_PTR_CONST(ptype) = 1; */
1667 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
1668 /* DCL_TYPE(ptype) = FPOINTER ; */
1670 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
1671 /* DCL_TYPE(ptype) = PPOINTER ; */
1673 /* if (SPEC_OCLS(etype) == idata) */
1674 /* DCL_TYPE(ptype) = IPOINTER; */
1676 /* DCL_TYPE(ptype) = POINTER ; */
1678 /* if the variable was declared a constant */
1679 /* then the pointer points to a constant */
1680 if (IS_CONSTANT(etype) )
1681 DCL_PTR_CONST(ptype) = 1;
1683 /* the variable was volatile then pointer to volatile */
1684 if (IS_VOLATILE(etype))
1685 DCL_PTR_VOLATILE(ptype) = 1;
1689 /*-----------------------------------------------------------------*/
1690 /* geniCodeArray2Ptr - array to pointer */
1691 /*-----------------------------------------------------------------*/
1692 operand *geniCodeArray2Ptr (operand *op)
1694 link *optype = operandType(op);
1695 link *opetype = getSpec(optype);
1697 if ((DCL_TYPE(optype) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1698 DCL_PTR_CONST(optype) = 1;
1700 /* set the pointer depending on the storage class */
1701 /* if (SPEC_OCLS(opetype)->codesp ) { */
1702 /* DCL_TYPE(optype) = CPOINTER ; */
1703 /* DCL_PTR_CONST(optype) = 1; */
1706 /* if (SPEC_OCLS(opetype)->fmap && !SPEC_OCLS(opetype)->paged) */
1707 /* DCL_TYPE(optype) = FPOINTER ; */
1709 /* if (SPEC_OCLS(opetype)->fmap && SPEC_OCLS(opetype)->paged) */
1710 /* DCL_TYPE(optype) = PPOINTER ; */
1712 /* if (SPEC_OCLS(opetype) == idata) */
1713 /* DCL_TYPE(optype) = IPOINTER; */
1715 /* DCL_TYPE(optype) = POINTER ; */
1717 /* if the variable was declared a constant */
1718 /* then the pointer points to a constant */
1719 if (IS_CONSTANT(opetype) )
1720 DCL_PTR_CONST(optype) = 1;
1722 /* the variable was volatile then pointer to volatile */
1723 if (IS_VOLATILE(opetype))
1724 DCL_PTR_VOLATILE(optype) = 1;
1729 /*-----------------------------------------------------------------*/
1730 /* geniCodeArray - array access */
1731 /*-----------------------------------------------------------------*/
1732 operand *geniCodeArray (operand *left,operand *right)
1735 link *ltype = operandType(left);
1737 if (IS_PTR(ltype)) {
1739 int olval = lvaluereq ;
1740 lvaluereq = IS_PTR(ltype->next);
1741 r= geniCodeDerefPtr(geniCodeAdd(left,right));
1747 right = geniCodeMultiply(right,
1748 operandFromLit(getSize(ltype->next)));
1750 /* we can check for limits here */
1751 if (isOperandLiteral(right) &&
1754 (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
1755 werror(E_ARRAY_BOUND);
1756 right = operandFromLit(0);
1759 ic = newiCode('+',left,right);
1761 IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) &&
1762 !IS_AGGREGATE(ltype->next) &&
1763 !IS_PTR(ltype->next))
1764 ? ltype : ltype->next),0);
1765 /* IC_RESULT(ic) = newiTempOperand(ltype->next,0); */
1766 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
1768 return IC_RESULT(ic) ;
1771 /*-----------------------------------------------------------------*/
1772 /* geniCodeStruct - generates intermediate code for structres */
1773 /*-----------------------------------------------------------------*/
1774 operand *geniCodeStruct (operand *left, operand *right, bool islval)
1777 link *type = operandType(left);
1778 link *etype = getSpec(type);
1780 symbol *element = getStructElement(SPEC_STRUCT(etype),
1781 right->operand.symOperand);
1783 /* add the offset */
1784 ic = newiCode('+',left,operandFromLit(element->offset));
1786 IC_RESULT(ic) = newiTempOperand(element->type,0);
1788 /* preserve the storage & output class of the struct */
1789 /* as well as the volatile attribute */
1790 retype = getSpec(operandType(IC_RESULT(ic)));
1791 SPEC_SCLS(retype) = SPEC_SCLS(etype);
1792 SPEC_OCLS(retype) = SPEC_OCLS(etype);
1793 SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);
1795 if (IS_PTR(element->type))
1796 setOperandType(IC_RESULT(ic),aggrToPtr(operandType(IC_RESULT(ic)),TRUE));
1798 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(element->type));
1802 return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
1805 /*-----------------------------------------------------------------*/
1806 /* geniCodePostInc - generate int code for Post increment */
1807 /*-----------------------------------------------------------------*/
1808 operand *geniCodePostInc (operand *op)
1812 link *optype = operandType(op);
1814 operand *rv = (IS_ITEMP(op) ?
1815 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1817 link *rvtype = operandType(rv);
1818 int diff = (IS_PTR(rvtype) && DCL_TYPE(optype) != DCL_TYPE(rvtype));
1821 /* if this is not an address we have trouble */
1822 if ( ! op->isaddr ) {
1823 werror (E_LVALUE_REQUIRED,"++");
1827 rOp = newiTempOperand((diff ? rvtype : optype),0);
1833 geniCodeAssign(rOp,rv,0);
1835 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1836 ic = newiCode('+',rv,operandFromLit(size));
1837 IC_RESULT(ic) = result =newiTempOperand((diff ? rvtype : optype),0);
1840 geniCodeAssign(op,result,0);
1846 /*-----------------------------------------------------------------*/
1847 /* geniCodePreInc - generate code for preIncrement */
1848 /*-----------------------------------------------------------------*/
1849 operand *geniCodePreInc (operand *op)
1852 link *optype = operandType(op);
1853 operand *rop = (IS_ITEMP(op) ?
1854 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1856 link *roptype = operandType(rop);
1857 int diff = (IS_PTR(roptype) && (DCL_TYPE(roptype) != DCL_TYPE(optype)));
1861 if ( ! op->isaddr ) {
1862 werror(E_LVALUE_REQUIRED,"++");
1867 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1868 ic = newiCode('+',rop,operandFromLit(size));
1869 IC_RESULT(ic) = result = newiTempOperand((diff ? roptype : optype),0) ;
1873 return geniCodeAssign(op,result,0) ;
1876 /*-----------------------------------------------------------------*/
1877 /* geniCodePostDec - generates code for Post decrement */
1878 /*-----------------------------------------------------------------*/
1879 operand *geniCodePostDec (operand *op)
1883 link *optype = operandType(op);
1885 operand *rv = (IS_ITEMP(op) ?
1886 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1888 link *rvtype = operandType(rv);
1889 int diff = (IS_PTR(rvtype) && DCL_TYPE(optype) != DCL_TYPE(rvtype));
1892 /* if this is not an address we have trouble */
1893 if ( ! op->isaddr ) {
1894 werror (E_LVALUE_REQUIRED,"++");
1898 rOp = newiTempOperand((diff ? rvtype : optype),0);
1904 geniCodeAssign(rOp,rv,0);
1906 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1907 ic = newiCode('-',rv,operandFromLit(size));
1908 IC_RESULT(ic) = result =newiTempOperand((diff ? rvtype : optype),0);
1911 geniCodeAssign(op,result,0);
1917 /*-----------------------------------------------------------------*/
1918 /* geniCodePreDec - generate code for pre decrement */
1919 /*-----------------------------------------------------------------*/
1920 operand *geniCodePreDec (operand *op)
1923 link *optype = operandType(op);
1924 operand *rop = (IS_ITEMP(op) ?
1925 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1927 link *roptype = operandType(rop);
1928 int diff = (IS_PTR(roptype) && (DCL_TYPE(roptype) != DCL_TYPE(optype)));
1932 if ( ! op->isaddr ) {
1933 werror(E_LVALUE_REQUIRED,"++");
1938 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1939 ic = newiCode('-',rop,operandFromLit(size));
1940 IC_RESULT(ic) = result = newiTempOperand((diff ? roptype : optype),0) ;
1944 return geniCodeAssign(op,result,0) ;
1948 /*-----------------------------------------------------------------*/
1949 /* geniCodeBitwise - gen int code for bitWise operators */
1950 /*-----------------------------------------------------------------*/
1951 operand *geniCodeBitwise (operand *left, operand *right,
1952 int oper, link *resType)
1956 left = geniCodeCast(resType,left,TRUE);
1957 right= geniCodeCast(resType,right,TRUE);
1959 ic = newiCode(oper,left,right);
1960 IC_RESULT(ic) = newiTempOperand(resType,0);
1963 return IC_RESULT(ic) ;
1966 /*-----------------------------------------------------------------*/
1967 /* geniCodeAddressOf - gens icode for '&' address of operator */
1968 /*-----------------------------------------------------------------*/
1969 operand *geniCodeAddressOf (operand *op)
1973 link *optype = operandType(op);
1974 link *opetype= getSpec(optype);
1976 /* this must be a lvalue */
1977 if (!op->isaddr && !IS_AGGREGATE(optype)) {
1978 werror (E_LVALUE_REQUIRED,"&");
1983 p->class = DECLARATOR ;
1985 if ((DCL_TYPE(p) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1986 DCL_PTR_CONST(p) = 1;
1988 /* set the pointer depending on the storage class */
1989 /* if (SPEC_OCLS(opetype)->codesp ) { */
1990 /* DCL_TYPE(p) = CPOINTER ; */
1991 /* DCL_PTR_CONST(p) = 1; */
1994 /* if (SPEC_OCLS(opetype)->fmap && !SPEC_OCLS(opetype)->paged) */
1995 /* DCL_TYPE(p) = FPOINTER ; */
1997 /* if (SPEC_OCLS(opetype)->fmap && SPEC_OCLS(opetype)->paged) */
1998 /* DCL_TYPE(p) = PPOINTER ; */
2000 /* if (SPEC_OCLS(opetype) == idata) */
2001 /* DCL_TYPE(p) = IPOINTER; */
2003 /* if (SPEC_OCLS(opetype) == data || */
2004 /* SPEC_OCLS(opetype) == overlay) */
2005 /* DCL_TYPE(p) = POINTER ; */
2007 /* DCL_TYPE(p) = GPOINTER; */
2009 /* make sure we preserve the const & volatile */
2010 if (IS_CONSTANT(opetype))
2011 DCL_PTR_CONST(p) = 1;
2013 if (IS_VOLATILE(opetype))
2014 DCL_PTR_VOLATILE(p) = 1;
2016 p->next = copyLinkChain(optype);
2018 /* if already a temp */
2020 setOperandType (op,p);
2025 /* other wise make this of the type coming in */
2026 ic = newiCode(ADDRESS_OF,op,NULL);
2027 IC_RESULT(ic) = newiTempOperand(p,1);
2028 IC_RESULT(ic)->isaddr = 0;
2030 return IC_RESULT(ic);
2032 /*-----------------------------------------------------------------*/
2033 /* setOClass - sets the output class depending on the pointer type */
2034 /*-----------------------------------------------------------------*/
2035 void setOClass (link *ptr, link *spec)
2037 switch (DCL_TYPE(ptr)) {
2039 SPEC_OCLS(spec) = data ;
2043 SPEC_OCLS(spec) = generic;
2047 SPEC_OCLS(spec) = xdata ;
2051 SPEC_OCLS(spec) = code ;
2055 SPEC_OCLS(spec) = idata;
2059 SPEC_OCLS(spec) = xstack;
2065 /*-----------------------------------------------------------------*/
2066 /* geniCodeDerefPtr - dereference pointer with '*' */
2067 /*-----------------------------------------------------------------*/
2068 operand *geniCodeDerefPtr (operand *op)
2070 link *rtype , *retype ;
2071 link *optype = operandType(op);
2073 /* if this is a pointer then generate the rvalue */
2074 if (IS_PTR(optype)) {
2075 if (IS_TRUE_SYMOP(op)) {
2077 op = geniCodeRValue(op,TRUE);
2080 op = geniCodeRValue(op,TRUE);
2083 /* now get rid of the pointer part */
2084 if (lvaluereq && IS_ITEMP(op))
2085 retype = getSpec(rtype = copyLinkChain(optype)) ;
2087 retype = getSpec(rtype = copyLinkChain(optype->next)) ;
2089 /* if this is a pointer then outputclass needs 2b updated */
2091 setOClass(optype,retype);
2093 op = geniCodeRValue(op,TRUE);
2094 op->isGptr = IS_GENPTR(optype);
2096 /* if the pointer was declared as a constant */
2097 /* then we cannot allow assignment to the derefed */
2098 if (IS_PTR_CONST(optype))
2099 SPEC_CONST(retype) = 1;
2102 setOperandType(op,rtype);
2103 op->isaddr = (IS_PTR(rtype) ||
2112 /*-----------------------------------------------------------------*/
2113 /* geniCodeUnaryMinus - does a unary minus of the operand */
2114 /*-----------------------------------------------------------------*/
2115 operand *geniCodeUnaryMinus (operand *op)
2118 link *optype = operandType(op);
2120 if (IS_LITERAL(optype))
2121 return operandFromLit(- floatFromVal(op->operand.valOperand));
2123 ic = newiCode(UNARYMINUS,op,NULL);
2124 IC_RESULT(ic) = newiTempOperand(optype,0);
2126 return IC_RESULT(ic);
2129 /*-----------------------------------------------------------------*/
2130 /* geniCodeLeftShift - gen i code for left shift */
2131 /*-----------------------------------------------------------------*/
2132 operand *geniCodeLeftShift (operand *left, operand *right)
2135 link *ltype = operandType(left);
2137 ic = newiCode(LEFT_OP,left,right);
2138 IC_RESULT(ic) = newiTempOperand(ltype,0);
2140 return IC_RESULT(ic) ;
2143 /*-----------------------------------------------------------------*/
2144 /* geniCodeRightShift - gen i code for right shift */
2145 /*-----------------------------------------------------------------*/
2146 operand *geniCodeRightShift (operand *left, operand *right)
2149 link *ltype = operandType(left);
2151 ic = newiCode(RIGHT_OP,left,right);
2152 IC_RESULT(ic) = newiTempOperand(ltype,0);
2154 return IC_RESULT(ic) ;
2157 /*-----------------------------------------------------------------*/
2158 /* geniCodeLogic- logic code */
2159 /*-----------------------------------------------------------------*/
2160 operand *geniCodeLogic (operand *left, operand *right, int op )
2164 link *rtype = operandType(right);
2165 link *ltype = operandType(left);
2167 /* left is integral type and right is literal then
2168 check if the literal value is within bounds */
2169 if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2170 int nbits = bitsForType(ltype);
2171 long v = operandLitValue(right);
2173 if (v > ((long long) 1 << nbits) && v > 0)
2174 werror(W_CONST_RANGE," compare operation ");
2177 ctype = computeType(ltype,rtype);
2178 left = geniCodeCast(ctype,left,TRUE);
2179 right= geniCodeCast(ctype,right,TRUE);
2181 ic = newiCode(op,left,right);
2182 IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2184 /* if comparing anything greater than one byte
2185 and not a '==' || '!=' || '&&' || '||' (these
2187 if (getSize(ctype) > 1 &&
2195 return IC_RESULT(ic);
2198 /*-----------------------------------------------------------------*/
2199 /* geniCodeUnary - for a a generic unary operation */
2200 /*-----------------------------------------------------------------*/
2201 operand *geniCodeUnary (operand *op, int oper )
2203 iCode *ic = newiCode (oper,op,NULL);
2205 IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2207 return IC_RESULT(ic) ;
2210 /*-----------------------------------------------------------------*/
2211 /* geniCodeConditional - geniCode for '?' ':' operation */
2212 /*-----------------------------------------------------------------*/
2213 operand *geniCodeConditional (ast *tree)
2216 symbol *falseLabel = newiTempLabel(NULL);
2217 symbol *exitLabel = newiTempLabel(NULL);
2218 operand *cond = ast2iCode(tree->left);
2219 operand *true, *false , *result;
2221 ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2225 true = ast2iCode(tree->right->left);
2227 /* move the value to a new Operand */
2228 result = newiTempOperand(operandType(true),0);
2229 geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2231 /* generate an unconditional goto */
2232 geniCodeGoto(exitLabel);
2234 /* now for the right side */
2235 geniCodeLabel(falseLabel);
2237 false = ast2iCode(tree->right->right);
2238 geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2240 /* create the exit label */
2241 geniCodeLabel(exitLabel);
2246 /*-----------------------------------------------------------------*/
2247 /* geniCodeAssign - generate code for assignment */
2248 /*-----------------------------------------------------------------*/
2249 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2252 link *ltype = operandType(left);
2253 link *rtype = operandType(right);
2255 if (!left->isaddr && !IS_ITEMP(left)) {
2256 werror(E_LVALUE_REQUIRED,"assignment");
2260 /* left is integral type and right is literal then
2261 check if the literal value is within bounds */
2262 if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2263 int nbits = bitsForType(ltype);
2264 long v = operandLitValue(right);
2266 if (v > ((long long)1 << nbits) && v > 0)
2267 werror(W_CONST_RANGE," = operation");
2269 /* if the left & right type don't exactly match */
2270 /* if pointer set then make sure the check is
2271 done with the type & not the pointer */
2272 /* then cast rights type to left */
2274 /* first check the type for pointer assignement */
2275 if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2276 checkType(ltype,rtype)<0) {
2277 if (checkType(ltype->next,rtype) < 0)
2278 right = geniCodeCast(ltype->next,right,TRUE);
2280 if (checkType(ltype,rtype) < 0 )
2281 right = geniCodeCast(ltype,right,TRUE);
2283 /* if left is a true symbol & ! volatile
2284 create an assignment to temporary for
2285 the right & then assign this temporary
2286 to the symbol this is SSA . isn't it simple
2287 and folks have published mountains of paper on it */
2288 if (IS_TRUE_SYMOP(left) &&
2289 !isOperandVolatile(left,FALSE) &&
2290 isOperandGlobal(left)) {
2293 if (IS_TRUE_SYMOP(right))
2294 sym = OP_SYMBOL(right);
2295 ic = newiCode('=',NULL,right);
2296 IC_RESULT(ic) = right = newiTempOperand(ltype,0);
2297 SPIL_LOC(right) = sym ;
2301 ic = newiCode('=',NULL,right);
2302 IC_RESULT(ic) = left;
2305 /* if left isgptr flag is set then support
2306 routine will be required */
2310 ic->nosupdate = nosupdate;
2314 /*-----------------------------------------------------------------*/
2315 /* geniCodeSEParms - generate code for side effecting fcalls */
2316 /*-----------------------------------------------------------------*/
2317 static void geniCodeSEParms (ast *parms)
2322 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2323 geniCodeSEParms (parms->left) ;
2324 geniCodeSEParms (parms->right);
2328 /* hack don't like this but too lazy to think of
2330 if (IS_ADDRESS_OF_OP(parms))
2331 parms->left->lvalue = 1;
2333 if (IS_CAST_OP(parms) &&
2334 IS_PTR(parms->ftype) &&
2335 IS_ADDRESS_OF_OP(parms->right))
2336 parms->right->left->lvalue = 1;
2338 parms->opval.oprnd =
2339 geniCodeRValue(ast2iCode (parms),TRUE);
2341 parms->type = EX_OPERAND ;
2344 /*-----------------------------------------------------------------*/
2345 /* geniCodeParms - generates parameters */
2346 /*-----------------------------------------------------------------*/
2347 static void geniCodeParms ( ast *parms , int *stack, link *fetype)
2355 /* if this is a param node then do the left & right */
2356 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2357 geniCodeParms (parms->left, stack,fetype) ;
2358 geniCodeParms (parms->right, stack,fetype);
2362 /* get the parameter value */
2363 if (parms->type == EX_OPERAND)
2364 pval = parms->opval.oprnd ;
2366 /* maybe this else should go away ?? */
2367 /* hack don't like this but too lazy to think of
2369 if (IS_ADDRESS_OF_OP(parms))
2370 parms->left->lvalue = 1;
2372 if (IS_CAST_OP(parms) &&
2373 IS_PTR(parms->ftype) &&
2374 IS_ADDRESS_OF_OP(parms->right))
2375 parms->right->left->lvalue = 1;
2377 pval = geniCodeRValue(ast2iCode (parms),FALSE);
2380 /* if register parm then make it a send */
2381 if ((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2382 IS_REGPARM(parms->etype)) {
2383 ic = newiCode(SEND,pval,NULL);
2386 /* now decide whether to push or assign */
2387 if (!(options.stackAuto || IS_RENT(fetype))) {
2390 operand *top = operandFromSymbol(parms->argSym);
2391 geniCodeAssign(top,pval,1);
2394 link *p = operandType(pval);
2396 ic = newiCode(IPUSH,pval,NULL);
2398 /* update the stack adjustment */
2399 *stack += getSize(IS_AGGREGATE(p)? aggrToPtr(p,FALSE):p);
2406 /*-----------------------------------------------------------------*/
2407 /* geniCodeCall - generates temp code for calling */
2408 /*-----------------------------------------------------------------*/
2409 operand *geniCodeCall (operand *left, ast *parms)
2416 /* take care of parameters with side-effecting
2417 function calls in them, this is required to take care
2418 of overlaying function parameters */
2419 if (!options.stackAuto)
2420 geniCodeSEParms ( parms );
2422 /* first the parameters */
2423 geniCodeParms ( parms , &stack , getSpec(operandType(left)));
2425 /* now call : if symbol then pcall */
2427 ic = newiCode(PCALL,left,NULL);
2429 ic = newiCode(CALL,left,NULL);
2431 IC_ARGS(ic) = left->operand.symOperand->args ;
2432 type = copyLinkChain(operandType(left)->next);
2433 etype = getSpec(type);
2434 SPEC_EXTR(etype) = 0;
2435 IC_RESULT(ic) = result = newiTempOperand(type,1);
2439 /* stack adjustment after call */
2440 left->parmBytes = stack;
2445 /*-----------------------------------------------------------------*/
2446 /* geniCodeReceive - generate intermediate code for "receive" */
2447 /*-----------------------------------------------------------------*/
2448 static void geniCodeReceive (value *args)
2450 /* for all arguments that are passed in registers */
2453 if (IS_REGPARM(args->etype)) {
2454 operand *opr = operandFromValue(args);
2456 symbol *sym = OP_SYMBOL(opr);
2459 /* we will use it after all optimizations
2460 and before liveRange calculation */
2461 if (!sym->addrtaken &&
2462 !IS_VOLATILE(sym->etype) &&
2463 !IN_FARSPACE(SPEC_OCLS(sym->etype))) {
2464 opl = newiTempOperand(args->type,0);
2466 sym->reqv->key = sym->key ;
2467 OP_SYMBOL(sym->reqv)->key = sym->key;
2468 OP_SYMBOL(sym->reqv)->isreqv = 1;
2469 OP_SYMBOL(sym->reqv)->islocal= 0;
2470 SPIL_LOC(sym->reqv) = sym;
2473 ic = newiCode(RECEIVE,NULL,NULL);
2474 currFunc->recvSize = getSize(sym->etype);
2475 IC_RESULT(ic) = opr;
2483 /*-----------------------------------------------------------------*/
2484 /* geniCodeFunctionBody - create the function body */
2485 /*-----------------------------------------------------------------*/
2486 void geniCodeFunctionBody (ast *tree)
2493 /* reset the auto generation */
2499 func = ast2iCode(tree->left);
2500 fetype = getSpec(operandType(func));
2502 savelineno = lineno;
2503 lineno = OP_SYMBOL(func)->lineDef;
2504 /* create an entry label */
2505 geniCodeLabel(entryLabel);
2506 lineno = savelineno;
2508 /* create a proc icode */
2509 ic = newiCode(FUNCTION,func,NULL);
2510 /* if the function has parmas then */
2511 /* save the parameters information */
2512 ic->argLabel.args = tree->values.args ;
2513 ic->lineno = OP_SYMBOL(func)->lineDef;
2517 /* for all parameters that are passed
2518 on registers add a "receive" */
2519 geniCodeReceive( tree->values.args );
2521 /* generate code for the body */
2522 ast2iCode(tree->right);
2524 /* create a label for return */
2525 geniCodeLabel(returnLabel);
2527 /* now generate the end proc */
2528 ic = newiCode(ENDFUNCTION,func,NULL);
2533 /*-----------------------------------------------------------------*/
2534 /* geniCodeReturn - gen icode for 'return' statement */
2535 /*-----------------------------------------------------------------*/
2536 void geniCodeReturn (operand *op)
2540 /* if the operand is present force an rvalue */
2542 op = geniCodeRValue(op,FALSE);
2544 ic = newiCode(RETURN,op,NULL);
2548 /*-----------------------------------------------------------------*/
2549 /* geniCodeIfx - generates code for extended if statement */
2550 /*-----------------------------------------------------------------*/
2551 void geniCodeIfx (ast *tree)
2554 operand *condition = ast2iCode(tree->left);
2555 /* link *ctype = operandType(condition); */
2558 /* if condition is null then exit */
2562 condition = geniCodeRValue(condition,FALSE);
2564 cetype = getSpec(operandType(condition));
2565 /* if the condition is a literal */
2566 if (IS_LITERAL(cetype)) {
2567 if (floatFromVal(condition->operand.valOperand)) {
2568 if (tree->trueLabel)
2569 geniCodeGoto(tree->trueLabel);
2574 if (tree->falseLabel)
2575 geniCodeGoto (tree->falseLabel);
2582 if ( tree->trueLabel ) {
2583 ic = newiCodeCondition(condition,
2588 if ( tree->falseLabel)
2589 geniCodeGoto(tree->falseLabel);
2592 ic = newiCodeCondition (condition,
2599 ast2iCode(tree->right);
2602 /*-----------------------------------------------------------------*/
2603 /* geniCodeJumpTable - tries to create a jump table for switch */
2604 /*-----------------------------------------------------------------*/
2605 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2607 int min = 0 ,max = 0, t, cnt = 0;
2612 set *labels = NULL ;
2614 if (!tree || !caseVals)
2617 /* the criteria for creating a jump table is */
2618 /* all integer numbers between the maximum & minimum must */
2619 /* be present , the maximum value should not exceed 255 */
2620 min = max = (int)floatFromVal(vch = caseVals);
2621 sprintf(buffer,"_case_%d_%d",
2622 tree->values.switchVals.swNum,
2624 addSet(&labels,newiTempLabel(buffer));
2626 /* if there is only one case value then no need */
2627 if (!(vch = vch->next ))
2631 if (((t = (int)floatFromVal(vch)) - max) != 1)
2633 sprintf(buffer,"_case_%d_%d",
2634 tree->values.switchVals.swNum,
2636 addSet(&labels,newiTempLabel(buffer));
2642 /* if the number of case statements <= 2 then */
2643 /* it is not economical to create the jump table */
2644 /* since two compares are needed for boundary conditions */
2645 if ((! optimize.noJTabBoundary && cnt <= 2) || max > (255/3))
2648 if ( tree->values.switchVals.swDefault )
2649 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2651 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2653 falseLabel = newiTempLabel (buffer);
2655 /* so we can create a jumptable */
2656 /* first we rule out the boundary conditions */
2657 /* if only optimization says so */
2658 if ( ! optimize.noJTabBoundary ) {
2659 link *cetype = getSpec(operandType(cond));
2660 /* no need to check the lower bound if
2661 the condition is unsigned & minimum value is zero */
2662 if (!( min == 0 && SPEC_USIGN(cetype))) {
2663 boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2664 ic = newiCodeCondition (boundary,falseLabel,NULL);
2668 /* now for upper bounds */
2669 boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2670 ic = newiCodeCondition (boundary,falseLabel,NULL);
2674 /* if the min is not zero then we no make it zero */
2676 cond = geniCodeSubtract(cond,operandFromLit(min));
2677 setOperandType(cond,ucharType);
2680 /* now create the jumptable */
2681 ic = newiCode(JUMPTABLE,NULL,NULL);
2682 IC_JTCOND(ic) = cond;
2683 IC_JTLABELS(ic) = labels;
2688 /*-----------------------------------------------------------------*/
2689 /* geniCodeSwitch - changes a switch to a if statement */
2690 /*-----------------------------------------------------------------*/
2691 void geniCodeSwitch (ast *tree)
2694 operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2695 value *caseVals = tree->values.switchVals.swVals ;
2696 symbol *trueLabel , *falseLabel;
2698 /* if we can make this a jump table */
2699 if ( geniCodeJumpTable (cond,caseVals,tree) )
2700 goto jumpTable ; /* no need for the comparison */
2702 /* for the cases defined do */
2705 operand *compare = geniCodeLogic (cond,
2706 operandFromValue(caseVals),
2709 sprintf(buffer,"_case_%d_%d",
2710 tree->values.switchVals.swNum,
2711 (int) floatFromVal(caseVals));
2712 trueLabel = newiTempLabel(buffer);
2714 ic = newiCodeCondition(compare,trueLabel,NULL);
2716 caseVals = caseVals->next;
2721 /* if default is present then goto break else break */
2722 if ( tree->values.switchVals.swDefault )
2723 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2725 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2727 falseLabel = newiTempLabel (buffer);
2728 geniCodeGoto(falseLabel);
2731 ast2iCode(tree->right);
2734 /*-----------------------------------------------------------------*/
2735 /* geniCodeInline - intermediate code for inline assembler */
2736 /*-----------------------------------------------------------------*/
2737 static void geniCodeInline (ast *tree)
2741 ic = newiCode(INLINEASM,NULL,NULL);
2742 IC_INLINE(ic) = tree->values.inlineasm;
2746 /*-----------------------------------------------------------------*/
2747 /* ast2iCode - creates an icodeList from an ast */
2748 /*-----------------------------------------------------------------*/
2749 operand *ast2iCode (ast *tree)
2751 operand *left = NULL;
2752 operand *right= NULL;
2757 /* set the global variables for filename & line number */
2758 if ( tree->filename )
2759 filename = tree->filename ;
2761 lineno = tree->lineno ;
2763 block = tree->block ;
2765 scopeLevel = tree->level;
2767 if (tree->type == EX_VALUE )
2768 return operandFromValue(tree->opval.val);
2770 if (tree->type == EX_LINK )
2771 return operandFromLink (tree->opval.lnk);
2773 /* if we find a nullop */
2774 if (tree->type == EX_OP &&
2775 ( tree->opval.op == NULLOP ||
2776 tree->opval.op == BLOCK )) {
2777 ast2iCode (tree->left);
2778 ast2iCode (tree->right);
2782 /* special cases for not evaluating */
2783 if ( tree->opval.op != ':' &&
2784 tree->opval.op != '?' &&
2785 tree->opval.op != CALL &&
2786 tree->opval.op != IFX &&
2787 tree->opval.op != LABEL &&
2788 tree->opval.op != GOTO &&
2789 tree->opval.op != SWITCH &&
2790 tree->opval.op != FUNCTION &&
2791 tree->opval.op != INLINEASM ) {
2792 if (IS_ASSIGN_OP(tree->opval.op) || IS_DEREF_OP(tree)) {
2794 left = operandFromAst(tree->left);
2797 left = operandFromAst(tree->left);
2799 right= operandFromAst(tree->right);
2802 /* now depending on the type of operand */
2803 /* this will be a biggy */
2804 switch (tree->opval.op) {
2806 case '[' : /* array operation */
2807 left= geniCodeRValue (left,FALSE);
2808 right=geniCodeRValue (right,TRUE);
2810 return geniCodeArray (left,right);
2812 case '.' : /* structure dereference */
2813 if (IS_PTR(operandType(left)))
2814 left = geniCodeRValue(left,TRUE);
2816 left = geniCodeRValue(left,FALSE);
2818 return geniCodeStruct (left,right,tree->lvalue);
2820 case PTR_OP: /* structure pointer dereference */
2823 pType = operandType(left);
2824 left = geniCodeRValue(left,TRUE);
2826 setOClass (pType,getSpec(operandType(left)));
2829 return geniCodeStruct (left, right,tree->lvalue);
2831 case INC_OP: /* increment operator */
2833 return geniCodePostInc (left);
2835 return geniCodePreInc (right);
2837 case DEC_OP: /* decrement operator */
2839 return geniCodePostDec (left);
2841 return geniCodePreDec (right);
2843 case '&' : /* bitwise and or address of operator */
2844 if ( right ) { /* this is a bitwise operator */
2845 left= geniCodeRValue(left,FALSE);
2846 right= geniCodeRValue(right,FALSE);
2847 return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
2849 return geniCodeAddressOf (left);
2851 case '|': /* bitwise or & xor */
2853 return geniCodeBitwise (geniCodeRValue(left,FALSE),
2854 geniCodeRValue(right,FALSE),
2859 return geniCodeDivision (geniCodeRValue(left,FALSE),
2860 geniCodeRValue(right,FALSE));
2863 return geniCodeModulus (geniCodeRValue(left,FALSE),
2864 geniCodeRValue(right,FALSE));
2867 return geniCodeMultiply (geniCodeRValue(left,FALSE),
2868 geniCodeRValue(right,FALSE));
2870 return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
2874 return geniCodeSubtract (geniCodeRValue(left,FALSE),
2875 geniCodeRValue(right,FALSE));
2877 return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
2881 return geniCodeAdd (geniCodeRValue(left,FALSE),
2882 geniCodeRValue(right,FALSE));
2884 return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
2887 return geniCodeLeftShift (geniCodeRValue(left,FALSE),
2888 geniCodeRValue(right,FALSE));
2891 return geniCodeRightShift (geniCodeRValue(left,FALSE),
2892 geniCodeRValue(right,FALSE));
2894 return geniCodeCast (operandType(left),
2895 geniCodeRValue(right,FALSE),FALSE);
2901 return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2905 operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2906 setOperandType(op,ucharType);
2917 return geniCodeLogic (geniCodeRValue(left,FALSE),
2918 geniCodeRValue(right,FALSE),
2921 return geniCodeConditional (tree);
2924 return operandFromLit(getSize(tree->right->ftype));
2928 link *rtype = operandType(right);
2929 link *ltype = operandType(left);
2930 if (IS_PTR(rtype) && IS_ITEMP(right)
2931 && right->isaddr && checkType(rtype->next,ltype)==1)
2932 right = geniCodeRValue(right,TRUE);
2934 right = geniCodeRValue(right,FALSE);
2936 geniCodeAssign (left,right,0);
2941 geniCodeAssign(left,
2942 geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
2944 geniCodeRValue(right,FALSE)),0);
2948 geniCodeAssign(left,
2949 geniCodeDivision(geniCodeRValue(operandFromOperand(left),
2951 geniCodeRValue(right,FALSE)),0);
2954 geniCodeAssign(left,
2955 geniCodeModulus(geniCodeRValue(operandFromOperand(left),
2957 geniCodeRValue(right,FALSE)),0);
2960 link *rtype = operandType(right);
2961 link *ltype = operandType(left);
2962 if (IS_PTR(rtype) && IS_ITEMP(right)
2963 && right->isaddr && checkType(rtype->next,ltype)==1)
2964 right = geniCodeRValue(right,TRUE);
2966 right = geniCodeRValue(right,FALSE);
2969 return geniCodeAssign(left,
2970 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
2976 link *rtype = operandType(right);
2977 link *ltype = operandType(left);
2978 if (IS_PTR(rtype) && IS_ITEMP(right)
2979 && right->isaddr && checkType(rtype->next,ltype)==1) {
2980 right = geniCodeRValue(right,TRUE);
2983 right = geniCodeRValue(right,FALSE);
2986 geniCodeAssign (left,
2987 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
2993 geniCodeAssign (left,
2994 geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
2996 geniCodeRValue(right,FALSE)),0);
2999 geniCodeAssign(left,
3000 geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
3002 geniCodeRValue(right,FALSE)),0);
3005 geniCodeAssign (left,
3006 geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
3008 geniCodeRValue(right,FALSE),
3010 operandType(left)),0);
3013 geniCodeAssign (left,
3014 geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3016 geniCodeRValue(right,FALSE),
3018 operandType(left)),0);
3021 geniCodeAssign (left,
3022 geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3024 geniCodeRValue(right,FALSE),
3026 operandType(left)),0);
3028 return geniCodeRValue(right,FALSE);
3031 return geniCodeCall (ast2iCode(tree->left),
3034 geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3035 return ast2iCode (tree->right);
3038 geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3039 return ast2iCode (tree->right);
3042 geniCodeFunctionBody ( tree );
3046 geniCodeReturn (right);
3054 geniCodeSwitch (tree);
3058 geniCodeInline (tree);
3065 /*-----------------------------------------------------------------*/
3066 /* reverseICChain - gets from the list and creates a linkedlist */
3067 /*-----------------------------------------------------------------*/
3068 iCode *reverseiCChain ()
3070 iCode *loop = NULL ;
3071 iCode *prev = NULL ;
3073 while ((loop = getSet(&iCodeChain))) {
3084 /*-----------------------------------------------------------------*/
3085 /* iCodeFromAst - given an ast will convert it to iCode */
3086 /*-----------------------------------------------------------------*/
3087 iCode *iCodeFromAst ( ast *tree )
3089 returnLabel = newiTempLabel("_return");
3090 entryLabel = newiTempLabel("_entry") ;
3092 return reverseiCChain ();