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 geniCodeSEParms ( parms );
2421 /* first the parameters */
2422 geniCodeParms ( parms , &stack , getSpec(operandType(left)));
2424 /* now call : if symbol then pcall */
2426 ic = newiCode(PCALL,left,NULL);
2428 ic = newiCode(CALL,left,NULL);
2430 IC_ARGS(ic) = left->operand.symOperand->args ;
2431 type = copyLinkChain(operandType(left)->next);
2432 etype = getSpec(type);
2433 SPEC_EXTR(etype) = 0;
2434 IC_RESULT(ic) = result = newiTempOperand(type,1);
2438 /* stack adjustment after call */
2439 left->parmBytes = stack;
2444 /*-----------------------------------------------------------------*/
2445 /* geniCodeReceive - generate intermediate code for "receive" */
2446 /*-----------------------------------------------------------------*/
2447 static void geniCodeReceive (value *args)
2449 /* for all arguments that are passed in registers */
2452 if (IS_REGPARM(args->etype)) {
2453 operand *opr = operandFromValue(args);
2455 symbol *sym = OP_SYMBOL(opr);
2458 /* we will use it after all optimizations
2459 and before liveRange calculation */
2460 if (!sym->addrtaken &&
2461 !IS_VOLATILE(sym->etype) &&
2462 !IN_FARSPACE(SPEC_OCLS(sym->etype))) {
2463 opl = newiTempOperand(args->type,0);
2465 sym->reqv->key = sym->key ;
2466 OP_SYMBOL(sym->reqv)->key = sym->key;
2467 OP_SYMBOL(sym->reqv)->isreqv = 1;
2468 OP_SYMBOL(sym->reqv)->islocal= 0;
2469 SPIL_LOC(sym->reqv) = sym;
2472 ic = newiCode(RECEIVE,NULL,NULL);
2473 currFunc->recvSize = getSize(sym->etype);
2474 IC_RESULT(ic) = opr;
2482 /*-----------------------------------------------------------------*/
2483 /* geniCodeFunctionBody - create the function body */
2484 /*-----------------------------------------------------------------*/
2485 void geniCodeFunctionBody (ast *tree)
2492 /* reset the auto generation */
2498 func = ast2iCode(tree->left);
2499 fetype = getSpec(operandType(func));
2501 savelineno = lineno;
2502 lineno = OP_SYMBOL(func)->lineDef;
2503 /* create an entry label */
2504 geniCodeLabel(entryLabel);
2505 lineno = savelineno;
2507 /* create a proc icode */
2508 ic = newiCode(FUNCTION,func,NULL);
2509 /* if the function has parmas then */
2510 /* save the parameters information */
2511 ic->argLabel.args = tree->values.args ;
2512 ic->lineno = OP_SYMBOL(func)->lineDef;
2516 /* for all parameters that are passed
2517 on registers add a "receive" */
2518 geniCodeReceive( tree->values.args );
2520 /* generate code for the body */
2521 ast2iCode(tree->right);
2523 /* create a label for return */
2524 geniCodeLabel(returnLabel);
2526 /* now generate the end proc */
2527 ic = newiCode(ENDFUNCTION,func,NULL);
2532 /*-----------------------------------------------------------------*/
2533 /* geniCodeReturn - gen icode for 'return' statement */
2534 /*-----------------------------------------------------------------*/
2535 void geniCodeReturn (operand *op)
2539 /* if the operand is present force an rvalue */
2541 op = geniCodeRValue(op,FALSE);
2543 ic = newiCode(RETURN,op,NULL);
2547 /*-----------------------------------------------------------------*/
2548 /* geniCodeIfx - generates code for extended if statement */
2549 /*-----------------------------------------------------------------*/
2550 void geniCodeIfx (ast *tree)
2553 operand *condition = ast2iCode(tree->left);
2554 /* link *ctype = operandType(condition); */
2557 /* if condition is null then exit */
2561 condition = geniCodeRValue(condition,FALSE);
2563 cetype = getSpec(operandType(condition));
2564 /* if the condition is a literal */
2565 if (IS_LITERAL(cetype)) {
2566 if (floatFromVal(condition->operand.valOperand)) {
2567 if (tree->trueLabel)
2568 geniCodeGoto(tree->trueLabel);
2573 if (tree->falseLabel)
2574 geniCodeGoto (tree->falseLabel);
2581 if ( tree->trueLabel ) {
2582 ic = newiCodeCondition(condition,
2587 if ( tree->falseLabel)
2588 geniCodeGoto(tree->falseLabel);
2591 ic = newiCodeCondition (condition,
2598 ast2iCode(tree->right);
2601 /*-----------------------------------------------------------------*/
2602 /* geniCodeJumpTable - tries to create a jump table for switch */
2603 /*-----------------------------------------------------------------*/
2604 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2606 int min = 0 ,max = 0, t, cnt = 0;
2611 set *labels = NULL ;
2613 if (!tree || !caseVals)
2616 /* the criteria for creating a jump table is */
2617 /* all integer numbers between the maximum & minimum must */
2618 /* be present , the maximum value should not exceed 255 */
2619 min = max = (int)floatFromVal(vch = caseVals);
2620 sprintf(buffer,"_case_%d_%d",
2621 tree->values.switchVals.swNum,
2623 addSet(&labels,newiTempLabel(buffer));
2625 /* if there is only one case value then no need */
2626 if (!(vch = vch->next ))
2630 if (((t = (int)floatFromVal(vch)) - max) != 1)
2632 sprintf(buffer,"_case_%d_%d",
2633 tree->values.switchVals.swNum,
2635 addSet(&labels,newiTempLabel(buffer));
2641 /* if the number of case statements <= 2 then */
2642 /* it is not economical to create the jump table */
2643 /* since two compares are needed for boundary conditions */
2644 if ((! optimize.noJTabBoundary && cnt <= 2) || max > (255/3))
2647 if ( tree->values.switchVals.swDefault )
2648 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2650 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2652 falseLabel = newiTempLabel (buffer);
2654 /* so we can create a jumptable */
2655 /* first we rule out the boundary conditions */
2656 /* if only optimization says so */
2657 if ( ! optimize.noJTabBoundary ) {
2658 link *cetype = getSpec(operandType(cond));
2659 /* no need to check the lower bound if
2660 the condition is unsigned & minimum value is zero */
2661 if (!( min == 0 && SPEC_USIGN(cetype))) {
2662 boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2663 ic = newiCodeCondition (boundary,falseLabel,NULL);
2667 /* now for upper bounds */
2668 boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2669 ic = newiCodeCondition (boundary,falseLabel,NULL);
2673 /* if the min is not zero then we no make it zero */
2675 cond = geniCodeSubtract(cond,operandFromLit(min));
2676 setOperandType(cond,ucharType);
2679 /* now create the jumptable */
2680 ic = newiCode(JUMPTABLE,NULL,NULL);
2681 IC_JTCOND(ic) = cond;
2682 IC_JTLABELS(ic) = labels;
2687 /*-----------------------------------------------------------------*/
2688 /* geniCodeSwitch - changes a switch to a if statement */
2689 /*-----------------------------------------------------------------*/
2690 void geniCodeSwitch (ast *tree)
2693 operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2694 value *caseVals = tree->values.switchVals.swVals ;
2695 symbol *trueLabel , *falseLabel;
2697 /* if we can make this a jump table */
2698 if ( geniCodeJumpTable (cond,caseVals,tree) )
2699 goto jumpTable ; /* no need for the comparison */
2701 /* for the cases defined do */
2704 operand *compare = geniCodeLogic (cond,
2705 operandFromValue(caseVals),
2708 sprintf(buffer,"_case_%d_%d",
2709 tree->values.switchVals.swNum,
2710 (int) floatFromVal(caseVals));
2711 trueLabel = newiTempLabel(buffer);
2713 ic = newiCodeCondition(compare,trueLabel,NULL);
2715 caseVals = caseVals->next;
2720 /* if default is present then goto break else break */
2721 if ( tree->values.switchVals.swDefault )
2722 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2724 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2726 falseLabel = newiTempLabel (buffer);
2727 geniCodeGoto(falseLabel);
2730 ast2iCode(tree->right);
2733 /*-----------------------------------------------------------------*/
2734 /* geniCodeInline - intermediate code for inline assembler */
2735 /*-----------------------------------------------------------------*/
2736 static void geniCodeInline (ast *tree)
2740 ic = newiCode(INLINEASM,NULL,NULL);
2741 IC_INLINE(ic) = tree->values.inlineasm;
2745 /*-----------------------------------------------------------------*/
2746 /* ast2iCode - creates an icodeList from an ast */
2747 /*-----------------------------------------------------------------*/
2748 operand *ast2iCode (ast *tree)
2750 operand *left = NULL;
2751 operand *right= NULL;
2756 /* set the global variables for filename & line number */
2757 if ( tree->filename )
2758 filename = tree->filename ;
2760 lineno = tree->lineno ;
2762 block = tree->block ;
2764 scopeLevel = tree->level;
2766 if (tree->type == EX_VALUE )
2767 return operandFromValue(tree->opval.val);
2769 if (tree->type == EX_LINK )
2770 return operandFromLink (tree->opval.lnk);
2772 /* if we find a nullop */
2773 if (tree->type == EX_OP &&
2774 ( tree->opval.op == NULLOP ||
2775 tree->opval.op == BLOCK )) {
2776 ast2iCode (tree->left);
2777 ast2iCode (tree->right);
2781 /* special cases for not evaluating */
2782 if ( tree->opval.op != ':' &&
2783 tree->opval.op != '?' &&
2784 tree->opval.op != CALL &&
2785 tree->opval.op != IFX &&
2786 tree->opval.op != LABEL &&
2787 tree->opval.op != GOTO &&
2788 tree->opval.op != SWITCH &&
2789 tree->opval.op != FUNCTION &&
2790 tree->opval.op != INLINEASM ) {
2791 if (IS_ASSIGN_OP(tree->opval.op) || IS_DEREF_OP(tree)) {
2793 left = operandFromAst(tree->left);
2796 left = operandFromAst(tree->left);
2798 right= operandFromAst(tree->right);
2801 /* now depending on the type of operand */
2802 /* this will be a biggy */
2803 switch (tree->opval.op) {
2805 case '[' : /* array operation */
2806 left= geniCodeRValue (left,FALSE);
2807 right=geniCodeRValue (right,TRUE);
2809 return geniCodeArray (left,right);
2811 case '.' : /* structure dereference */
2812 if (IS_PTR(operandType(left)))
2813 left = geniCodeRValue(left,TRUE);
2815 left = geniCodeRValue(left,FALSE);
2817 return geniCodeStruct (left,right,tree->lvalue);
2819 case PTR_OP: /* structure pointer dereference */
2822 pType = operandType(left);
2823 left = geniCodeRValue(left,TRUE);
2825 setOClass (pType,getSpec(operandType(left)));
2828 return geniCodeStruct (left, right,tree->lvalue);
2830 case INC_OP: /* increment operator */
2832 return geniCodePostInc (left);
2834 return geniCodePreInc (right);
2836 case DEC_OP: /* decrement operator */
2838 return geniCodePostDec (left);
2840 return geniCodePreDec (right);
2842 case '&' : /* bitwise and or address of operator */
2843 if ( right ) { /* this is a bitwise operator */
2844 left= geniCodeRValue(left,FALSE);
2845 right= geniCodeRValue(right,FALSE);
2846 return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
2848 return geniCodeAddressOf (left);
2850 case '|': /* bitwise or & xor */
2852 return geniCodeBitwise (geniCodeRValue(left,FALSE),
2853 geniCodeRValue(right,FALSE),
2858 return geniCodeDivision (geniCodeRValue(left,FALSE),
2859 geniCodeRValue(right,FALSE));
2862 return geniCodeModulus (geniCodeRValue(left,FALSE),
2863 geniCodeRValue(right,FALSE));
2866 return geniCodeMultiply (geniCodeRValue(left,FALSE),
2867 geniCodeRValue(right,FALSE));
2869 return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
2873 return geniCodeSubtract (geniCodeRValue(left,FALSE),
2874 geniCodeRValue(right,FALSE));
2876 return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
2880 return geniCodeAdd (geniCodeRValue(left,FALSE),
2881 geniCodeRValue(right,FALSE));
2883 return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
2886 return geniCodeLeftShift (geniCodeRValue(left,FALSE),
2887 geniCodeRValue(right,FALSE));
2890 return geniCodeRightShift (geniCodeRValue(left,FALSE),
2891 geniCodeRValue(right,FALSE));
2893 return geniCodeCast (operandType(left),
2894 geniCodeRValue(right,FALSE),FALSE);
2900 return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2904 operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2905 setOperandType(op,ucharType);
2916 return geniCodeLogic (geniCodeRValue(left,FALSE),
2917 geniCodeRValue(right,FALSE),
2920 return geniCodeConditional (tree);
2923 return operandFromLit(getSize(tree->right->ftype));
2927 link *rtype = operandType(right);
2928 link *ltype = operandType(left);
2929 if (IS_PTR(rtype) && IS_ITEMP(right)
2930 && right->isaddr && checkType(rtype->next,ltype)==1)
2931 right = geniCodeRValue(right,TRUE);
2933 right = geniCodeRValue(right,FALSE);
2935 geniCodeAssign (left,right,0);
2940 geniCodeAssign(left,
2941 geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
2943 geniCodeRValue(right,FALSE)),0);
2947 geniCodeAssign(left,
2948 geniCodeDivision(geniCodeRValue(operandFromOperand(left),
2950 geniCodeRValue(right,FALSE)),0);
2953 geniCodeAssign(left,
2954 geniCodeModulus(geniCodeRValue(operandFromOperand(left),
2956 geniCodeRValue(right,FALSE)),0);
2959 link *rtype = operandType(right);
2960 link *ltype = operandType(left);
2961 if (IS_PTR(rtype) && IS_ITEMP(right)
2962 && right->isaddr && checkType(rtype->next,ltype)==1)
2963 right = geniCodeRValue(right,TRUE);
2965 right = geniCodeRValue(right,FALSE);
2968 return geniCodeAssign(left,
2969 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
2975 link *rtype = operandType(right);
2976 link *ltype = operandType(left);
2977 if (IS_PTR(rtype) && IS_ITEMP(right)
2978 && right->isaddr && checkType(rtype->next,ltype)==1) {
2979 right = geniCodeRValue(right,TRUE);
2982 right = geniCodeRValue(right,FALSE);
2985 geniCodeAssign (left,
2986 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
2992 geniCodeAssign (left,
2993 geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
2995 geniCodeRValue(right,FALSE)),0);
2998 geniCodeAssign(left,
2999 geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
3001 geniCodeRValue(right,FALSE)),0);
3004 geniCodeAssign (left,
3005 geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
3007 geniCodeRValue(right,FALSE),
3009 operandType(left)),0);
3012 geniCodeAssign (left,
3013 geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3015 geniCodeRValue(right,FALSE),
3017 operandType(left)),0);
3020 geniCodeAssign (left,
3021 geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3023 geniCodeRValue(right,FALSE),
3025 operandType(left)),0);
3027 return geniCodeRValue(right,FALSE);
3030 return geniCodeCall (ast2iCode(tree->left),
3033 geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3034 return ast2iCode (tree->right);
3037 geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3038 return ast2iCode (tree->right);
3041 geniCodeFunctionBody ( tree );
3045 geniCodeReturn (right);
3053 geniCodeSwitch (tree);
3057 geniCodeInline (tree);
3064 /*-----------------------------------------------------------------*/
3065 /* reverseICChain - gets from the list and creates a linkedlist */
3066 /*-----------------------------------------------------------------*/
3067 iCode *reverseiCChain ()
3069 iCode *loop = NULL ;
3070 iCode *prev = NULL ;
3072 while ((loop = getSet(&iCodeChain))) {
3083 /*-----------------------------------------------------------------*/
3084 /* iCodeFromAst - given an ast will convert it to iCode */
3085 /*-----------------------------------------------------------------*/
3086 iCode *iCodeFromAst ( ast *tree )
3088 returnLabel = newiTempLabel("_return");
3089 entryLabel = newiTempLabel("_entry") ;
3091 return reverseiCChain ();