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
154 fprintf(file,"{"); printTypeChain(operandType(op),file);
155 if (SPIL_LOC(op) && IS_ITEMP(op))
156 fprintf(file,"}{ sir@ %s",SPIL_LOC(op)->rname);
161 /* if assigned to registers */
162 if (OP_SYMBOL(op)->nRegs) {
163 if (OP_SYMBOL(op)->isspilt) {
164 if (!OP_SYMBOL(op)->remat)
165 if (OP_SYMBOL(op)->usl.spillLoc)
166 fprintf(file,"[%s]",(OP_SYMBOL(op)->usl.spillLoc->rname[0] ?
167 OP_SYMBOL(op)->usl.spillLoc->rname :
168 OP_SYMBOL(op)->usl.spillLoc->name));
170 fprintf(file,"[err]");
172 fprintf(file,"[remat]");
177 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
178 fprintf(file,"%s ", port->getRegName(OP_SYMBOL(op)->regs[i]));
183 fprintf(file,"%s",(OP_SYMBOL(op)->rname[0] ?
184 OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name));
185 /* if assigned to registers */
186 if (OP_SYMBOL(op)->nRegs && !OP_SYMBOL(op)->isspilt) {
189 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
190 fprintf(file,"%s ",(OP_SYMBOL(op)->regs[i] ?
191 OP_SYMBOL(op)->regs[i]->name :
200 printTypeChain(op->operand.typeOperand,file);
211 /*-----------------------------------------------------------------*/
212 /* print functions */
213 /*-----------------------------------------------------------------*/
214 PRINTFUNC(picGetValueAtAddr)
217 printOperand (IC_RESULT(ic),of);
220 printOperand (IC_LEFT(ic), of);
226 PRINTFUNC(picSetValueAtAddr)
230 printOperand(IC_LEFT(ic),of);
232 printOperand(IC_RIGHT(ic),of);
239 printOperand(IC_RESULT(ic),of);
240 if (IS_ITEMP(IC_LEFT(ic)))
244 printOperand(IC_LEFT(ic),of);
246 if (IS_ITEMP(IC_LEFT(ic)))
247 fprintf(of," offsetAdd ");
250 printOperand(IC_RIGHT(ic),of);
252 if (IS_ITEMP(IC_LEFT(ic)))
258 PRINTFUNC(picJumpTable)
263 fprintf(of,"%s\t",s);
264 printOperand(IC_JTCOND(ic),of);
266 for ( sym = setFirstItem(IC_JTLABELS(ic)); sym;
267 sym = setNextItem(IC_JTLABELS(ic)))
268 fprintf(of,"\t\t\t%s\n",sym->name);
271 PRINTFUNC(picGeneric)
274 printOperand(IC_RESULT(ic),of);
276 printOperand(IC_LEFT(ic),of);
277 fprintf(of," %s ",s);
278 printOperand(IC_RIGHT(ic),of);
282 PRINTFUNC(picGenericOne)
285 if ( IC_RESULT(ic) ) {
286 printOperand(IC_RESULT(ic),of);
291 fprintf (of,"%s ",s);
292 printOperand(IC_LEFT(ic),of);
295 if (! IC_RESULT(ic) && !IC_LEFT(ic))
304 printOperand(IC_RESULT(ic),of);
306 printOperand(IC_LEFT(ic),of);
307 printOperand(IC_RIGHT(ic),of);
316 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
319 printOperand(IC_RESULT(ic),of);
321 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
324 fprintf(of," %s ", s);
325 printOperand (IC_RIGHT(ic),of);
332 fprintf(of," %s($%d) :\n",IC_LABEL(ic)->name,IC_LABEL(ic)->key);
338 fprintf (of," goto %s($%d)\n", IC_LABEL(ic)->name,IC_LABEL(ic)->key);
345 printOperand(IC_COND(ic),of);
348 fprintf (of," == 0 goto %s($%d)\n",IC_FALSE(ic)->name,IC_FALSE(ic)->key);
350 fprintf (of," != 0 goto %s($%d)\n",IC_TRUE(ic)->name,IC_TRUE(ic)->key);
352 fprintf (of,"\tzzgoto %s\n",IC_FALSE(ic)->name);
358 fprintf(of,"%s",IC_INLINE(ic));
361 PRINTFUNC(picReceive)
363 printOperand(IC_RESULT(ic),of);
364 fprintf(of," = %s ",s);
365 printOperand(IC_LEFT(ic),of);
369 /*-----------------------------------------------------------------*/
370 /* piCode - prints one iCode */
371 /*-----------------------------------------------------------------*/
372 int piCode (void *item, FILE *of)
380 icTab = getTableEntry(ic->op) ;
381 fprintf(stdout,"%s(%d:%d:%d:%d:%d)\t",
382 ic->filename,ic->lineno,
383 ic->seq,ic->key,ic->depth,ic->supportRtn);
384 icTab->iCodePrint(of,ic,icTab->printName);
388 /*-----------------------------------------------------------------*/
389 /* printiCChain - prints intermediate code for humans */
390 /*-----------------------------------------------------------------*/
391 void printiCChain (iCode *icChain, FILE *of)
398 for ( loop = icChain ; loop ; loop = loop->next ) {
399 if ((icTab = getTableEntry (loop->op ))) {
400 fprintf(of,"%s(%d:%d:%d:%d:%d)\t",
401 loop->filename,loop->lineno,
402 loop->seq,loop->key,loop->depth,loop->supportRtn);
404 icTab->iCodePrint (of,loop,icTab->printName);
410 /*-----------------------------------------------------------------*/
411 /* newOperand - allocate, init & return a new iCode */
412 /*-----------------------------------------------------------------*/
413 operand *newOperand ()
417 ALLOC(op,sizeof(operand));
423 /*-----------------------------------------------------------------*/
424 /* newiCode - create and return a new iCode entry initialised */
425 /*-----------------------------------------------------------------*/
426 iCode *newiCode (int op, operand *left, operand *right)
430 ALLOC(ic,sizeof(iCode));
432 ic->lineno = lineno ;
433 ic->filename= filename ;
435 ic->level = scopeLevel;
437 ic->key= iCodeKey++ ;
444 /*-----------------------------------------------------------------*/
445 /* newiCode for conditional statements */
446 /*-----------------------------------------------------------------*/
447 iCode *newiCodeCondition (operand *condition,
453 ic = newiCode(IFX,NULL,NULL);
454 IC_COND(ic) = condition ;
455 IC_TRUE(ic) = trueLabel ;
456 IC_FALSE(ic) = falseLabel;
460 /*-----------------------------------------------------------------*/
461 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
462 /*-----------------------------------------------------------------*/
463 iCode *newiCodeLabelGoto (int op, symbol *label)
467 ic = newiCode(op,NULL,NULL);
469 ic->argLabel.label = label ;
471 IC_RIGHT(ic) = NULL ;
472 IC_RESULT(ic) = NULL ;
476 /*-----------------------------------------------------------------*/
477 /* newiTemp - allocate & return a newItemp Variable */
478 /*-----------------------------------------------------------------*/
479 symbol *newiTemp (char *s)
484 sprintf(buffer,"%s",s);
486 sprintf (buffer,"iTemp%d",iTempNum++);
487 itmp = newSymbol (buffer,1);
488 strcpy(itmp->rname,itmp->name);
494 /*-----------------------------------------------------------------*/
495 /* newiTempLabel - creates a temp variable label */
496 /*-----------------------------------------------------------------*/
497 symbol *newiTempLabel (char *s)
501 /* check if this alredy exists */
502 if (s && (itmplbl = findSym(LabelTab, NULL, s)))
506 itmplbl = newSymbol(s,1);
508 sprintf(buffer,"iTempLbl%d",iTempLblNum++);
509 itmplbl = newSymbol(buffer,1);
514 itmplbl->key = labelKey++ ;
515 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
519 /*-----------------------------------------------------------------*/
520 /* newiTempPreheaderLabel - creates a new preheader label */
521 /*-----------------------------------------------------------------*/
522 symbol *newiTempPreheaderLabel()
526 sprintf(buffer,"preHeaderLbl%d",iTempLblNum++);
527 itmplbl = newSymbol(buffer,1);
531 itmplbl->key = labelKey++ ;
532 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
537 /*-----------------------------------------------------------------*/
538 /* initiCode - initialises some iCode related stuff */
539 /*-----------------------------------------------------------------*/
545 /*-----------------------------------------------------------------*/
546 /* copyiCode - make a copy of the iCode given */
547 /*-----------------------------------------------------------------*/
548 iCode *copyiCode (iCode *ic)
550 iCode *nic = newiCode(ic->op,NULL,NULL);
552 nic->lineno = ic->lineno ;
553 nic->filename= ic->filename ;
554 nic->block = ic->block;
555 nic->level = ic->level;
557 /* deal with the special cases first */
560 IC_COND(nic) = operandFromOperand(IC_COND(ic));
561 IC_TRUE(nic) = IC_TRUE(ic);
562 IC_FALSE(nic)= IC_FALSE(ic);
566 IC_JTCOND(nic) = operandFromOperand(IC_JTCOND(ic));
567 IC_JTLABELS(nic) = IC_JTLABELS(ic);
572 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
573 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
574 IC_ARGS(nic) = IC_ARGS(ic);
578 IC_INLINE(nic) = IC_INLINE(ic);
582 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
583 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
584 IC_RIGHT(nic)= operandFromOperand(IC_RIGHT(ic));
590 /*-----------------------------------------------------------------*/
591 /* getTableEntry - gets the table entry for the given operator */
592 /*-----------------------------------------------------------------*/
593 iCodeTable *getTableEntry (int oper )
597 for ( i = 0 ; i < (sizeof(codeTable)/sizeof(iCodeTable)); i++ )
598 if (oper == codeTable[i].icode)
599 return &codeTable[i] ;
604 /*-----------------------------------------------------------------*/
605 /* newiTempOperand - new intermediate temp operand */
606 /*-----------------------------------------------------------------*/
607 operand *newiTempOperand (link *type, char throwType)
610 operand *op = newOperand();
614 itmp = newiTemp(NULL);
616 etype = getSpec(type);
618 if (IS_LITERAL(etype) )
621 /* copy the type information */
623 itmp->etype = getSpec (itmp->type = (throwType ? type :
624 copyLinkChain(type)));
625 if (IS_LITERAL(itmp->etype)) {
626 SPEC_SCLS(itmp->etype) = S_REGISTER ;
627 SPEC_OCLS(itmp->etype) = reg;
630 op->operand.symOperand = itmp;
631 op->key = itmp->key = ++operandKey ;
635 /*-----------------------------------------------------------------*/
636 /* operandType - returns the type chain for an operand */
637 /*-----------------------------------------------------------------*/
638 link *operandType (operand *op)
640 /* depending on type of operand */
644 return op->operand.valOperand->type ;
647 return op->operand.symOperand->type ;
650 return op->operand.typeOperand ;
653 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
654 " operand type not known ");
655 assert (0) ; /* should never come here */
656 /* Just to keep the compiler happy */
660 /*-----------------------------------------------------------------*/
661 /* isParamterToCall - will return 1 if op is a parameter to args */
662 /*-----------------------------------------------------------------*/
663 int isParameterToCall (value *args, operand *op)
669 isSymbolEqual(op->operand.symOperand,tval->sym))
676 /*-----------------------------------------------------------------*/
677 /* isOperandGlobal - return 1 if operand is a global variable */
678 /*-----------------------------------------------------------------*/
679 int isOperandGlobal ( operand *op )
687 if (op->type == SYMBOL &&
688 (op->operand.symOperand->level == 0 ||
689 IS_STATIC(op->operand.symOperand->etype) ||
690 IS_EXTERN(op->operand.symOperand->etype))
697 /*-----------------------------------------------------------------*/
698 /* isOperandVolatile - return 1 if the operand is volatile */
699 /*-----------------------------------------------------------------*/
700 int isOperandVolatile ( operand *op , bool chkTemp)
705 if (IS_ITEMP(op) && !chkTemp)
708 opetype = getSpec(optype = operandType(op));
710 if (IS_PTR(optype) && DCL_PTR_VOLATILE(optype))
713 if (IS_VOLATILE(opetype))
718 /*-----------------------------------------------------------------*/
719 /* isOperandLiteral - returns 1 if an operand contains a literal */
720 /*-----------------------------------------------------------------*/
721 int isOperandLiteral ( operand *op )
728 opetype = getSpec (operandType(op));
730 if (IS_LITERAL(opetype))
735 /*-----------------------------------------------------------------*/
736 /* isOperandInFarSpace - will return true if operand is in farSpace*/
737 /*-----------------------------------------------------------------*/
738 bool isOperandInFarSpace (operand *op)
748 if (!IS_TRUE_SYMOP(op)) {
750 etype = SPIL_LOC(op)->etype;
755 etype = getSpec(operandType(op));
756 return (IN_FARSPACE(SPEC_OCLS(etype)) ? TRUE : FALSE);
759 /*-----------------------------------------------------------------*/
760 /* operandLitValue - literal value of an operand */
761 /*-----------------------------------------------------------------*/
762 double operandLitValue ( operand *op )
764 assert(isOperandLiteral(op));
766 return floatFromVal(op->operand.valOperand);
769 /*-----------------------------------------------------------------*/
770 /* operandOperation - perforoms operations on operands */
771 /*-----------------------------------------------------------------*/
772 operand *operandOperation (operand *left,operand *right,
775 operand *retval = (operand *)0;
777 assert(isOperandLiteral(left));
779 assert(isOperandLiteral(right));
783 retval = operandFromValue (valCastLiteral(type,
784 operandLitValue(left) +
785 operandLitValue(right)));
788 retval = operandFromValue(valCastLiteral(type,
789 operandLitValue(left) -
790 operandLitValue(right)));
793 retval = operandFromValue(valCastLiteral(type,
794 operandLitValue(left) *
795 operandLitValue(right)));
798 if ((unsigned long) operandLitValue(right) == 0){
799 werror(E_DIVIDE_BY_ZERO);
804 retval = operandFromValue (valCastLiteral(type,
805 operandLitValue(left) /
806 operandLitValue(right)));
809 if ((unsigned long) operandLitValue(right) == 0){
810 werror(E_DIVIDE_BY_ZERO);
814 retval = operandFromLit ((unsigned long) operandLitValue(left) %
815 (unsigned long) operandLitValue(right));
818 retval = operandFromLit ((unsigned long) operandLitValue(left) <<
819 (unsigned long) operandLitValue(right));
822 retval = operandFromLit ((unsigned long) operandLitValue(left) >>
823 (unsigned long) operandLitValue(right));
826 retval = operandFromLit (operandLitValue(left) ==
827 operandLitValue(right));
830 retval = operandFromLit (operandLitValue(left) <
831 operandLitValue(right));
834 retval = operandFromLit (operandLitValue(left) <=
835 operandLitValue(right));
838 retval = operandFromLit (operandLitValue(left) !=
839 operandLitValue(right));
842 retval = operandFromLit (operandLitValue(left) >
843 operandLitValue(right));
846 retval = operandFromLit (operandLitValue(left) >=
847 operandLitValue(right));
850 retval = operandFromLit ((unsigned long) operandLitValue(left) &
851 (unsigned long) operandLitValue(right));
854 retval = operandFromLit ((unsigned long) operandLitValue(left) |
855 (unsigned long) operandLitValue(right));
858 retval = operandFromLit ((unsigned long) operandLitValue(left) ^
859 (unsigned long) operandLitValue(right));
862 retval = operandFromLit (operandLitValue(left) &&
863 operandLitValue(right));
866 retval = operandFromLit (operandLitValue(left) ||
867 operandLitValue(right));
871 long i = operandLitValue(left);
873 retval = operandFromLit ((i >> (getSize(operandType(left))*8 - 1)) |
879 long i = operandLitValue(left);
881 retval = operandFromLit ((i << (getSize(operandType(left))*8 - 1)) |
887 retval = operandFromLit(-1 * operandLitValue(left));
891 retval = operandFromLit(~ ((long) operandLitValue(left)));
895 retval = operandFromLit(! operandLitValue(left));
899 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
900 " operandOperation invalid operator ");
908 /*-----------------------------------------------------------------*/
909 /* isOperandEqual - compares two operand & return 1 if they r = */
910 /*-----------------------------------------------------------------*/
911 int isOperandEqual (operand *left, operand *right)
913 /* if the pointers are equal then they are equal */
917 /* if either of them null then false */
918 if ( !left || !right)
921 if (left->type != right->type)
924 if (IS_SYMOP(left) && IS_SYMOP(right))
925 return left->key == right->key ;
927 /* if types are the same */
928 switch (left->type) {
930 return isSymbolEqual(left->operand.symOperand,
931 right->operand.symOperand);
933 return (floatFromVal(left->operand.valOperand) ==
934 floatFromVal(right->operand.valOperand));
936 if (checkType(left->operand.typeOperand,
937 right->operand.typeOperand) == 1)
944 /*-----------------------------------------------------------------*/
945 /* isiCodeEqual - comapres two iCodes are returns true if yes */
946 /*-----------------------------------------------------------------*/
947 int isiCodeEqual (iCode *left, iCode *right)
949 /* if the same pointer */
953 /* if either of them null */
957 /* if operand are the same */
958 if ( left->op == right->op ) {
960 /* compare all the elements depending on type */
961 if (left->op != IFX ) {
962 if (!isOperandEqual(IC_LEFT(left),IC_LEFT(right)))
964 if (!isOperandEqual(IC_RIGHT(left),IC_RIGHT(right)))
968 if (!isOperandEqual(IC_COND(left),IC_COND(right)))
970 if (!isSymbolEqual (IC_TRUE(left),IC_TRUE(right)))
972 if (!isSymbolEqual(IC_FALSE(left),IC_FALSE(right)))
980 /*-----------------------------------------------------------------*/
981 /* newiTempFromOp - create a temp Operand with same attributes */
982 /*-----------------------------------------------------------------*/
983 operand *newiTempFromOp (operand *op)
993 nop = newiTempOperand(operandType(op),TRUE);
994 nop->isaddr = op->isaddr ;
995 nop->isvolatile = op->isvolatile ;
996 nop->isGlobal = op->isGlobal ;
997 nop->isLiteral= op->isLiteral ;
998 nop->noSpilLoc= op->noSpilLoc;
999 nop->usesDefs = op->usesDefs;
1000 nop->isParm = op->isParm;
1001 nop->parmBytes = op->parmBytes;
1005 /*-----------------------------------------------------------------*/
1006 /* operand from operand - creates an operand holder for the type */
1007 /*-----------------------------------------------------------------*/
1008 operand *operandFromOperand (operand *op)
1015 nop->type = op->type;
1016 nop->isaddr = op->isaddr ;
1017 nop->key = op->key ;
1018 nop->isvolatile = op->isvolatile ;
1019 nop->isGlobal = op->isGlobal ;
1020 nop->isLiteral= op->isLiteral ;
1021 nop->noSpilLoc= op->noSpilLoc;
1022 nop->usesDefs = op->usesDefs;
1023 nop->isParm = op->isParm;
1024 nop->parmBytes = op->parmBytes;
1026 switch (nop->type) {
1028 nop->operand.symOperand = op->operand.symOperand ;
1031 nop->operand.valOperand = op->operand.valOperand;
1034 nop->operand.typeOperand = op->operand.typeOperand ;
1041 /*-----------------------------------------------------------------*/
1042 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1043 /*-----------------------------------------------------------------*/
1044 operand *opFromOpWithDU (operand *op, bitVect *defs, bitVect *uses)
1046 operand *nop = operandFromOperand(op);
1048 if (nop->type == SYMBOL) {
1049 OP_SYMBOL(nop)->defs = bitVectCopy(defs);
1050 OP_SYMBOL(nop)->uses = bitVectCopy(uses);
1056 /*-----------------------------------------------------------------*/
1057 /* operandFromSymbol - creates an operand from a symbol */
1058 /*-----------------------------------------------------------------*/
1059 operand *operandFromSymbol (symbol *sym)
1064 /* if the symbol's type is a literal */
1065 /* then it is an enumerator type */
1066 if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype))
1067 return operandFromValue (valFromType(sym->etype));
1070 sym->key = ++operandKey ;
1072 /* if this an implicit variable, means struct/union */
1073 /* member so just return it */
1074 if (sym->implicit || IS_FUNC(sym->type)) {
1077 op->operand.symOperand = sym;
1078 op->key = sym->key ;
1079 op->isvolatile = isOperandVolatile(op,TRUE);
1080 op->isGlobal = isOperandGlobal(op);
1081 op->parmBytes = sym->argStack;
1085 /* under the following conditions create a
1086 register equivalent for a local symbol */
1087 if (!IS_AGGREGATE(sym->type) && /* not an aggregate */
1088 !IS_FUNC(sym->type) && /* not a function */
1089 !sym->_isparm && /* not a parameter */
1090 sym->level && /* is a local variable */
1091 !sym->addrtaken && /* whose address has not been taken */
1092 !sym->reqv && /* does not already have a register euivalence */
1093 !IS_VOLATILE(sym->etype) && /* not declared as volatile */
1094 !IS_STATIC(sym->etype) && /* and not declared static */
1095 !sym->islbl && /* not a label */
1096 !IN_FARSPACE(SPEC_OCLS(sym->etype)) && /* not in far space */
1097 !IS_BITVAR(sym->etype) /* not a bit variable */
1100 /* we will use it after all optimizations
1101 and before liveRange calculation */
1102 sym->reqv = newiTempOperand(sym->type,0);
1103 sym->reqv->key = sym->key ;
1104 OP_SYMBOL(sym->reqv)->key = sym->key;
1105 OP_SYMBOL(sym->reqv)->isreqv = 1;
1106 OP_SYMBOL(sym->reqv)->islocal = 1;
1107 SPIL_LOC(sym->reqv) = sym;
1110 if (!IS_AGGREGATE(sym->type)) {
1113 op->operand.symOperand = sym;
1116 op->isvolatile = isOperandVolatile(op,TRUE);
1117 op->isGlobal = isOperandGlobal(op);
1118 op->isPtr = IS_PTR(operandType(op));
1119 op->isParm = sym->_isparm ;
1124 /* itemp = &[_symbol] */
1126 ic = newiCode(ADDRESS_OF,newOperand(),NULL);
1127 IC_LEFT(ic)->type = SYMBOL ;
1128 IC_LEFT(ic)->operand.symOperand = sym ;
1129 IC_LEFT(ic)->key = sym->key;
1130 (IC_LEFT(ic))->isvolatile = isOperandVolatile(IC_LEFT(ic),TRUE);
1131 (IC_LEFT(ic))->isGlobal = isOperandGlobal(IC_LEFT(ic));
1132 IC_LEFT(ic)->isPtr = IS_PTR(operandType(IC_LEFT(ic)));
1135 IC_RESULT(ic) = newiTempOperand(sym->type,0);
1136 if (IS_ARRAY(sym->type)) {
1137 IC_RESULT(ic) = geniCodeArray2Ptr (IC_RESULT(ic));
1138 IC_RESULT(ic)->isaddr = 0;
1140 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(sym->type));
1142 IC_RESULT(ic)->operand.symOperand->args = sym->args;
1146 return IC_RESULT(ic) ;
1149 /*-----------------------------------------------------------------*/
1150 /* operandFromValue - creates an operand from value */
1151 /*-----------------------------------------------------------------*/
1152 operand *operandFromValue (value *val)
1156 /* if this is a symbol then do the symbol thing */
1158 return operandFromSymbol (val->sym);
1160 /* this is not a symbol */
1163 op->operand.valOperand = val ;
1164 op->isLiteral = isOperandLiteral(op);
1168 /*-----------------------------------------------------------------*/
1169 /* operandFromLink - operand from typeChain */
1170 /*-----------------------------------------------------------------*/
1171 operand *operandFromLink (link *type)
1175 /* operand from link */
1181 op->operand.typeOperand = copyLinkChain(type);
1185 /*-----------------------------------------------------------------*/
1186 /* operandFromLit - makes an operand from a literal value */
1187 /*-----------------------------------------------------------------*/
1188 operand *operandFromLit ( float i)
1190 return operandFromValue (valueFromLit (i));
1193 /*-----------------------------------------------------------------*/
1194 /* operandFromAst - creates an operand from an ast */
1195 /*-----------------------------------------------------------------*/
1196 operand *operandFromAst ( ast *tree )
1202 /* depending on type do */
1203 switch (tree->type ) {
1205 return ast2iCode (tree) ;
1209 return operandFromValue(tree->opval.val) ;
1213 return operandFromLink (tree->opval.lnk) ;
1217 /* Just to keep the comiler happy */
1218 return (operand *)0;
1221 /*-----------------------------------------------------------------*/
1222 /* setOperandType - sets the operand's type to the given type */
1223 /*-----------------------------------------------------------------*/
1224 void setOperandType (operand *op, link *type)
1226 /* depending on the type of operand */
1230 op->operand.valOperand->etype =
1231 getSpec( op->operand.valOperand->type =
1232 copyLinkChain (type )) ;
1236 if (op->operand.symOperand->isitmp )
1237 op->operand.symOperand->etype =
1238 getSpec( op->operand.symOperand->type =
1239 copyLinkChain (type )) ;
1241 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
1242 "attempt to modify type of source");
1246 op->operand.typeOperand = copyLinkChain (type);
1252 /*-----------------------------------------------------------------*/
1253 /* geniCodeValueAtAddress - generate intermeditate code for value */
1255 /*-----------------------------------------------------------------*/
1256 operand *geniCodeRValue (operand *op, bool force)
1259 link *type = operandType(op);
1260 link *etype= getSpec(type);
1262 /* if this is an array & already */
1263 /* an address then return this */
1264 if (IS_AGGREGATE(type) ||
1265 (IS_PTR(type) && !force && !op->isaddr))
1266 return operandFromOperand(op);
1268 /* if this is not an address then must be */
1269 /* rvalue already so return this one */
1273 /* if this is not a temp symbol then */
1274 if (!IS_ITEMP(op) &&
1276 !IN_FARSPACE(SPEC_OCLS(etype))) {
1277 op = operandFromOperand(op);
1282 if (IS_SPEC(type) &&
1283 IS_TRUE_SYMOP(op) &&
1284 !IN_FARSPACE(SPEC_OCLS(etype))) {
1285 op = operandFromOperand(op);
1290 ic = newiCode(GET_VALUE_AT_ADDRESS,op,NULL);
1291 if (IS_PTR(type) && op->isaddr && force)
1294 type = copyLinkChain(type);
1296 IC_RESULT(ic) = newiTempOperand (type,1);
1297 IC_RESULT(ic)->isaddr = 0;
1299 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1301 /* if the right is a symbol */
1302 if (op->type == SYMBOL)
1303 IC_RESULT(ic)->operand.symOperand->args =
1304 op->operand.symOperand->args ;
1307 return IC_RESULT(ic) ;
1310 /*-----------------------------------------------------------------*/
1311 /* geniCodeCast - changes the value from one type to another */
1312 /*-----------------------------------------------------------------*/
1313 operand *geniCodeCast (link *type, operand *op, bool implicit)
1317 link *opetype = getSpec(optype = operandType(op));
1320 /* one of them has size zero then error */
1321 if (IS_VOID(optype)) {
1322 werror(E_CAST_ZERO);
1326 /* if the operand is already the desired type then do nothing */
1327 if ( checkType (type,optype) == 1)
1330 /* if this is a literal then just change the type & return */
1331 if (IS_LITERAL(opetype) && !IS_PTR(type) && !IS_PTR(optype))
1332 return operandFromValue(valCastLiteral(type,
1333 operandLitValue(op)));
1335 /* if casting to some pointer type &&
1336 the destination is not a generic pointer
1337 then give a warning : (only for implicit casts)*/
1338 if (IS_PTR(optype) && implicit &&
1339 (DCL_TYPE(optype) != DCL_TYPE(type)) &&
1341 werror(E_INCOMPAT_CAST);
1342 werror(E_CONTINUE,"from type '");
1343 printTypeChain(optype,stderr);fprintf(stderr,"' to type '");
1344 printTypeChain(type,stderr);fprintf(stderr,"'\n");
1347 /* if they are the same size create an assignment */
1348 if (getSize(type) == getSize(optype) &&
1349 !IS_BITFIELD(type) &&
1351 !IS_FLOAT(optype) &&
1352 ((IS_SPEC(type) && IS_SPEC(optype)) ||
1353 (!IS_SPEC(type) && !IS_SPEC(optype)))) {
1355 ic = newiCode('=',NULL,op);
1356 IC_RESULT(ic) = newiTempOperand(type,0);
1357 SPIL_LOC(IC_RESULT(ic)) =
1358 (IS_TRUE_SYMOP(op) ? OP_SYMBOL(op) : NULL);
1359 IC_RESULT(ic)->isaddr = 0;
1361 ic = newiCode(CAST,operandFromLink(type),
1362 geniCodeRValue(op,FALSE));
1364 IC_RESULT(ic)= newiTempOperand(type,0);
1367 /* preserve the storage class & output class */
1368 /* of the original variable */
1369 restype = getSpec(operandType(IC_RESULT(ic)));
1370 SPEC_SCLS(restype) = SPEC_SCLS(opetype);
1371 SPEC_OCLS(restype) = SPEC_OCLS(opetype);
1374 return IC_RESULT(ic) ;
1377 /*-----------------------------------------------------------------*/
1378 /* geniCodeLabel - will create a Label */
1379 /*-----------------------------------------------------------------*/
1380 void geniCodeLabel (symbol *label)
1384 ic = newiCodeLabelGoto(LABEL,label);
1388 /*-----------------------------------------------------------------*/
1389 /* geniCodeGoto - will create a Goto */
1390 /*-----------------------------------------------------------------*/
1391 void geniCodeGoto (symbol *label)
1395 ic = newiCodeLabelGoto(GOTO,label);
1399 /*-----------------------------------------------------------------*/
1400 /* geniCodeMultiply - gen intermediate code for multiplication */
1401 /*-----------------------------------------------------------------*/
1402 operand *geniCodeMultiply (operand *left, operand *right)
1409 /* if they are both literal then we know the result */
1410 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1411 return operandFromValue (valMult(left->operand.valOperand,
1412 right->operand.valOperand));
1414 resType = computeType (ltype,rtype) ;
1415 left = geniCodeCast(resType,left,TRUE);
1416 right= geniCodeCast(resType,right,TRUE);
1418 /* if the right is a literal & power of 2 */
1419 /* then make it a left shift */
1420 if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
1421 (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand))))
1422 ic = newiCode(LEFT_OP, left,operandFromLit(p2)); /* left shift */
1424 ic = newiCode('*',left,right); /* normal multiplication */
1425 /* if the size left or right > 1 then support routine */
1426 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1430 IC_RESULT(ic) = newiTempOperand(resType,1);
1433 return IC_RESULT(ic) ;
1436 /*-----------------------------------------------------------------*/
1437 /* geniCodeDivision - gen intermediate code for division */
1438 /*-----------------------------------------------------------------*/
1439 operand *geniCodeDivision (operand *left, operand *right)
1444 link *rtype = operandType(right);
1445 link *retype= getSpec(rtype);
1446 link *ltype = operandType(left);
1447 link *letype= getSpec(ltype);
1449 resType = computeType (ltype,rtype) ;
1450 left = geniCodeCast(resType,left,TRUE);
1451 right= geniCodeCast(resType,right,TRUE);
1453 /* if the right is a literal & power of 2 */
1454 /* then make it a right shift */
1455 if (IS_LITERAL(retype) &&
1456 !IS_FLOAT(letype) &&
1457 (p2 = powof2 ((unsigned long)
1458 floatFromVal(right->operand.valOperand))))
1459 ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
1461 ic = newiCode('/',left,right); /* normal division */
1462 /* if the size left or right > 1 then support routine */
1463 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1466 IC_RESULT(ic) = newiTempOperand(resType,0);
1469 return IC_RESULT(ic) ;
1471 /*-----------------------------------------------------------------*/
1472 /* geniCodeModulus - gen intermediate code for modulus */
1473 /*-----------------------------------------------------------------*/
1474 operand *geniCodeModulus (operand *left, operand *right)
1480 /* if they are both literal then we know the result */
1481 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1482 return operandFromValue (valMod(left->operand.valOperand,
1483 right->operand.valOperand));
1485 resType = computeType (ltype,rtype) ;
1486 left = geniCodeCast(resType,left,TRUE);
1487 right= geniCodeCast(resType,right,TRUE);
1489 /* now they are the same size */
1490 ic = newiCode('%',left,right);
1492 /* if the size left or right > 1 then support routine */
1493 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1495 IC_RESULT(ic) = newiTempOperand(resType,0);
1498 return IC_RESULT(ic) ;
1501 /*-----------------------------------------------------------------*/
1502 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1503 /*-----------------------------------------------------------------*/
1504 operand *geniCodePtrPtrSubtract (operand *left, operand *right)
1510 /* if they are both literals then */
1511 if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
1512 result = operandFromValue (valMinus(left->operand.valOperand,
1513 right->operand.valOperand));
1517 ic = newiCode('-',left,right);
1519 IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
1523 return geniCodeDivision (result,
1524 operandFromLit(getSize(ltype->next)));
1527 /*-----------------------------------------------------------------*/
1528 /* geniCodeSubtract - generates code for subtraction */
1529 /*-----------------------------------------------------------------*/
1530 operand *geniCodeSubtract (operand *left, operand *right)
1537 /* if they both pointers then */
1538 if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
1539 (IS_PTR(rtype) || IS_ARRAY(rtype)))
1540 return geniCodePtrPtrSubtract (left,right);
1542 /* if they are both literal then we know the result */
1543 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1544 return operandFromValue (valMinus(left->operand.valOperand,
1545 right->operand.valOperand));
1547 /* if left is an array or pointer */
1548 if ( IS_PTR(ltype) || IS_ARRAY(ltype) ) {
1549 isarray = left->isaddr ;
1550 right = geniCodeMultiply (right,
1551 operandFromLit(getSize(ltype->next)));
1552 resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
1554 else { /* make them the same size */
1555 resType = computeType (ltype,rtype) ;
1556 left = geniCodeCast(resType,left,TRUE);
1557 right= geniCodeCast(resType,right,TRUE);
1560 ic = newiCode('-',left,right);
1562 IC_RESULT(ic)= newiTempOperand(resType,1);
1563 IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
1565 /* if left or right is a float */
1566 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1570 return IC_RESULT(ic) ;
1573 /*-----------------------------------------------------------------*/
1574 /* geniCodeAdd - generates iCode for addition */
1575 /*-----------------------------------------------------------------*/
1576 operand *geniCodeAdd (operand *left, operand *right )
1584 /* if left is an array then array access */
1585 if (IS_ARRAY(ltype))
1586 return geniCodeArray (left,right);
1588 /* if the right side is LITERAL zero */
1589 /* return the left side */
1590 if (IS_LITERAL(retype) && !floatFromVal(valFromType(retype)))
1593 /* if left is literal zero return right */
1594 if (IS_LITERAL(letype) && !floatFromVal(valFromType(letype)))
1597 /* if left is an array or pointer then size */
1598 if (IS_PTR(ltype)) {
1600 isarray = left->isaddr;
1602 operandFromLit(getSize(ltype->next));
1603 right = geniCodeMultiply (right ,size);
1604 resType = copyLinkChain(ltype);
1606 else { /* make them the same size */
1607 resType = computeType (ltype,rtype) ;
1608 left = geniCodeCast(resType,left,TRUE);
1609 right= geniCodeCast(resType,right,TRUE);
1612 /* if they are both literals then we know */
1613 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1614 return operandFromValue (valPlus(valFromType(letype),
1615 valFromType(retype)));
1617 ic = newiCode('+',left,right);
1619 IC_RESULT(ic) = newiTempOperand(resType,1);
1620 IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
1622 /* if left or right is a float then support
1624 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1629 return IC_RESULT(ic) ;
1633 /*-----------------------------------------------------------------*/
1634 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1635 /*-----------------------------------------------------------------*/
1636 link *aggrToPtr ( link *type, bool force)
1642 if (IS_PTR(type) && !force)
1645 etype = getSpec(type);
1649 /* if the output class is generic */
1650 if ((DCL_TYPE(ptype) = PTR_TYPE(SPEC_OCLS(etype))) == CPOINTER)
1651 DCL_PTR_CONST(ptype) = 1;
1653 /* if (SPEC_OCLS(etype) == generic) */
1654 /* DCL_TYPE(ptype) = GPOINTER; */
1656 /* if (SPEC_OCLS(etype)->codesp ) { */
1657 /* DCL_TYPE(ptype) = CPOINTER ; */
1658 /* DCL_PTR_CONST(ptype) = 1; */
1661 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
1662 /* DCL_TYPE(ptype) = FPOINTER ; */
1664 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
1665 /* DCL_TYPE(ptype) = PPOINTER ; */
1667 /* if (SPEC_OCLS(etype) == idata) */
1668 /* DCL_TYPE(ptype) = IPOINTER; */
1670 /* DCL_TYPE(ptype) = POINTER ; */
1672 /* if the variable was declared a constant */
1673 /* then the pointer points to a constant */
1674 if (IS_CONSTANT(etype) )
1675 DCL_PTR_CONST(ptype) = 1;
1677 /* the variable was volatile then pointer to volatile */
1678 if (IS_VOLATILE(etype))
1679 DCL_PTR_VOLATILE(ptype) = 1;
1683 /*-----------------------------------------------------------------*/
1684 /* geniCodeArray2Ptr - array to pointer */
1685 /*-----------------------------------------------------------------*/
1686 operand *geniCodeArray2Ptr (operand *op)
1688 link *optype = operandType(op);
1689 link *opetype = getSpec(optype);
1691 if ((DCL_TYPE(optype) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1692 DCL_PTR_CONST(optype) = 1;
1694 /* set the pointer depending on the storage class */
1695 /* if (SPEC_OCLS(opetype)->codesp ) { */
1696 /* DCL_TYPE(optype) = CPOINTER ; */
1697 /* DCL_PTR_CONST(optype) = 1; */
1700 /* if (SPEC_OCLS(opetype)->fmap && !SPEC_OCLS(opetype)->paged) */
1701 /* DCL_TYPE(optype) = FPOINTER ; */
1703 /* if (SPEC_OCLS(opetype)->fmap && SPEC_OCLS(opetype)->paged) */
1704 /* DCL_TYPE(optype) = PPOINTER ; */
1706 /* if (SPEC_OCLS(opetype) == idata) */
1707 /* DCL_TYPE(optype) = IPOINTER; */
1709 /* DCL_TYPE(optype) = POINTER ; */
1711 /* if the variable was declared a constant */
1712 /* then the pointer points to a constant */
1713 if (IS_CONSTANT(opetype) )
1714 DCL_PTR_CONST(optype) = 1;
1716 /* the variable was volatile then pointer to volatile */
1717 if (IS_VOLATILE(opetype))
1718 DCL_PTR_VOLATILE(optype) = 1;
1723 /*-----------------------------------------------------------------*/
1724 /* geniCodeArray - array access */
1725 /*-----------------------------------------------------------------*/
1726 operand *geniCodeArray (operand *left,operand *right)
1729 link *ltype = operandType(left);
1731 if (IS_PTR(ltype)) {
1732 return geniCodeDerefPtr(geniCodeAdd(left,right));
1736 right = geniCodeMultiply(right,
1737 operandFromLit(getSize(ltype->next)));
1739 /* we can check for limits here */
1740 if (isOperandLiteral(right) &&
1743 (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
1744 werror(E_ARRAY_BOUND);
1745 right = operandFromLit(0);
1748 ic = newiCode('+',left,right);
1750 IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) &&
1751 !IS_AGGREGATE(ltype->next) &&
1752 !IS_PTR(ltype->next))
1753 ? ltype : ltype->next),0);
1755 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
1757 return IC_RESULT(ic) ;
1760 /*-----------------------------------------------------------------*/
1761 /* geniCodeStruct - generates intermediate code for structres */
1762 /*-----------------------------------------------------------------*/
1763 operand *geniCodeStruct (operand *left, operand *right, bool islval)
1766 link *type = operandType(left);
1767 link *etype = getSpec(type);
1769 symbol *element = getStructElement(SPEC_STRUCT(etype),
1770 right->operand.symOperand);
1772 /* add the offset */
1773 ic = newiCode('+',left,operandFromLit(element->offset));
1775 IC_RESULT(ic) = newiTempOperand(element->type,0);
1777 /* preserve the storage & output class of the struct */
1778 /* as well as the volatile attribute */
1779 retype = getSpec(operandType(IC_RESULT(ic)));
1780 SPEC_SCLS(retype) = SPEC_SCLS(etype);
1781 SPEC_OCLS(retype) = SPEC_OCLS(etype);
1782 SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);
1784 if (IS_PTR(element->type))
1785 setOperandType(IC_RESULT(ic),aggrToPtr(operandType(IC_RESULT(ic)),TRUE));
1787 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(element->type));
1791 return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
1794 /*-----------------------------------------------------------------*/
1795 /* geniCodePostInc - generate int code for Post increment */
1796 /*-----------------------------------------------------------------*/
1797 operand *geniCodePostInc (operand *op)
1801 link *optype = operandType(op);
1803 operand *rv = (IS_ITEMP(op) ?
1804 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1806 link *rvtype = operandType(rv);
1809 /* if this is not an address we have trouble */
1810 if ( ! op->isaddr ) {
1811 werror (E_LVALUE_REQUIRED,"++");
1815 rOp = newiTempOperand(rvtype,0);
1821 geniCodeAssign(rOp,rv,0);
1823 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1824 ic = newiCode('+',rv,operandFromLit(size));
1825 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1828 geniCodeAssign(op,result,0);
1834 /*-----------------------------------------------------------------*/
1835 /* geniCodePreInc - generate code for preIncrement */
1836 /*-----------------------------------------------------------------*/
1837 operand *geniCodePreInc (operand *op)
1840 link *optype = operandType(op);
1841 operand *rop = (IS_ITEMP(op) ?
1842 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1844 link *roptype = operandType(rop);
1848 if ( ! op->isaddr ) {
1849 werror(E_LVALUE_REQUIRED,"++");
1854 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1855 ic = newiCode('+',rop,operandFromLit(size));
1856 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1860 return geniCodeAssign(op,result,0) ;
1863 /*-----------------------------------------------------------------*/
1864 /* geniCodePostDec - generates code for Post decrement */
1865 /*-----------------------------------------------------------------*/
1866 operand *geniCodePostDec (operand *op)
1870 link *optype = operandType(op);
1872 operand *rv = (IS_ITEMP(op) ?
1873 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1875 link *rvtype = operandType(rv);
1878 /* if this is not an address we have trouble */
1879 if ( ! op->isaddr ) {
1880 werror (E_LVALUE_REQUIRED,"++");
1884 rOp = newiTempOperand(rvtype,0);
1890 geniCodeAssign(rOp,rv,0);
1892 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1893 ic = newiCode('-',rv,operandFromLit(size));
1894 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1897 geniCodeAssign(op,result,0);
1903 /*-----------------------------------------------------------------*/
1904 /* geniCodePreDec - generate code for pre decrement */
1905 /*-----------------------------------------------------------------*/
1906 operand *geniCodePreDec (operand *op)
1909 link *optype = operandType(op);
1910 operand *rop = (IS_ITEMP(op) ?
1911 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1913 link *roptype = operandType(rop);
1917 if ( ! op->isaddr ) {
1918 werror(E_LVALUE_REQUIRED,"++");
1923 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1924 ic = newiCode('-',rop,operandFromLit(size));
1925 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1929 return geniCodeAssign(op,result,0) ;
1933 /*-----------------------------------------------------------------*/
1934 /* geniCodeBitwise - gen int code for bitWise operators */
1935 /*-----------------------------------------------------------------*/
1936 operand *geniCodeBitwise (operand *left, operand *right,
1937 int oper, link *resType)
1941 left = geniCodeCast(resType,left,TRUE);
1942 right= geniCodeCast(resType,right,TRUE);
1944 ic = newiCode(oper,left,right);
1945 IC_RESULT(ic) = newiTempOperand(resType,0);
1948 return IC_RESULT(ic) ;
1951 /*-----------------------------------------------------------------*/
1952 /* geniCodeAddressOf - gens icode for '&' address of operator */
1953 /*-----------------------------------------------------------------*/
1954 operand *geniCodeAddressOf (operand *op)
1958 link *optype = operandType(op);
1959 link *opetype= getSpec(optype);
1961 /* this must be a lvalue */
1962 if (!op->isaddr && !IS_AGGREGATE(optype)) {
1963 werror (E_LVALUE_REQUIRED,"&");
1968 p->class = DECLARATOR ;
1970 if ((DCL_TYPE(p) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1971 DCL_PTR_CONST(p) = 1;
1973 /* set the pointer depending on the storage class */
1974 /* if (SPEC_OCLS(opetype)->codesp ) { */
1975 /* DCL_TYPE(p) = CPOINTER ; */
1976 /* DCL_PTR_CONST(p) = 1; */
1979 /* if (SPEC_OCLS(opetype)->fmap && !SPEC_OCLS(opetype)->paged) */
1980 /* DCL_TYPE(p) = FPOINTER ; */
1982 /* if (SPEC_OCLS(opetype)->fmap && SPEC_OCLS(opetype)->paged) */
1983 /* DCL_TYPE(p) = PPOINTER ; */
1985 /* if (SPEC_OCLS(opetype) == idata) */
1986 /* DCL_TYPE(p) = IPOINTER; */
1988 /* if (SPEC_OCLS(opetype) == data || */
1989 /* SPEC_OCLS(opetype) == overlay) */
1990 /* DCL_TYPE(p) = POINTER ; */
1992 /* DCL_TYPE(p) = GPOINTER; */
1994 /* make sure we preserve the const & volatile */
1995 if (IS_CONSTANT(opetype))
1996 DCL_PTR_CONST(p) = 1;
1998 if (IS_VOLATILE(opetype))
1999 DCL_PTR_VOLATILE(p) = 1;
2001 p->next = copyLinkChain(optype);
2003 /* if already a temp */
2005 setOperandType (op,p);
2010 /* other wise make this of the type coming in */
2011 ic = newiCode(ADDRESS_OF,op,NULL);
2012 IC_RESULT(ic) = newiTempOperand(p,1);
2013 IC_RESULT(ic)->isaddr = 0;
2015 return IC_RESULT(ic);
2017 /*-----------------------------------------------------------------*/
2018 /* setOClass - sets the output class depending on the pointer type */
2019 /*-----------------------------------------------------------------*/
2020 void setOClass (link *ptr, link *spec)
2022 switch (DCL_TYPE(ptr)) {
2024 SPEC_OCLS(spec) = data ;
2028 SPEC_OCLS(spec) = generic;
2032 SPEC_OCLS(spec) = xdata ;
2036 SPEC_OCLS(spec) = code ;
2040 SPEC_OCLS(spec) = idata;
2044 SPEC_OCLS(spec) = xstack;
2049 /*-----------------------------------------------------------------*/
2050 /* geniCodeDerefPtr - dereference pointer with '*' */
2051 /*-----------------------------------------------------------------*/
2052 operand *geniCodeDerefPtr (operand *op)
2054 link *rtype , *retype ;
2055 link *optype = operandType(op);
2057 /* if this is a pointer then generate the rvalue */
2058 if (IS_PTR(optype)) {
2059 if (IS_TRUE_SYMOP(op)) {
2061 op = geniCodeRValue(op,TRUE);
2064 op = geniCodeRValue(op,TRUE);
2067 /* now get rid of the pointer part */
2068 if (lvaluereq && IS_ITEMP(op) && !IS_PTR(optype->next))
2070 retype = getSpec(rtype = copyLinkChain(optype)) ;
2074 retype = getSpec(rtype = copyLinkChain(optype->next)) ;
2077 /* if this is a pointer then outputclass needs 2b updated */
2079 setOClass(optype,retype);
2082 /* This block moved here from its original location
2083 * ten lines later by KV, 2/27/2000.
2085 * This allows code of the form "&array[const]" to
2089 op = geniCodeRValue(op, TRUE);
2091 op->isGptr = IS_GENPTR(optype);
2093 /* if the pointer was declared as a constant */
2094 /* then we cannot allow assignment to the derefed */
2095 if (IS_PTR_CONST(optype))
2096 SPEC_CONST(retype) = 1;
2098 op->isaddr = (IS_PTR(rtype) ||
2107 op = geniCodeRValue(op,TRUE);
2109 setOperandType(op,rtype);
2114 /*-----------------------------------------------------------------*/
2115 /* geniCodeUnaryMinus - does a unary minus of the operand */
2116 /*-----------------------------------------------------------------*/
2117 operand *geniCodeUnaryMinus (operand *op)
2120 link *optype = operandType(op);
2122 if (IS_LITERAL(optype))
2123 return operandFromLit(- floatFromVal(op->operand.valOperand));
2125 ic = newiCode(UNARYMINUS,op,NULL);
2126 IC_RESULT(ic) = newiTempOperand(optype,0);
2128 return IC_RESULT(ic);
2131 /*-----------------------------------------------------------------*/
2132 /* geniCodeLeftShift - gen i code for left shift */
2133 /*-----------------------------------------------------------------*/
2134 operand *geniCodeLeftShift (operand *left, operand *right)
2137 link *ltype = operandType(left);
2139 ic = newiCode(LEFT_OP,left,right);
2140 IC_RESULT(ic) = newiTempOperand(ltype,0);
2142 return IC_RESULT(ic) ;
2145 /*-----------------------------------------------------------------*/
2146 /* geniCodeRightShift - gen i code for right shift */
2147 /*-----------------------------------------------------------------*/
2148 operand *geniCodeRightShift (operand *left, operand *right)
2151 link *ltype = operandType(left);
2153 ic = newiCode(RIGHT_OP,left,right);
2154 IC_RESULT(ic) = newiTempOperand(ltype,0);
2156 return IC_RESULT(ic) ;
2160 #define LONG_LONG __int64
2162 #define LONG_LONG long long
2165 /*-----------------------------------------------------------------*/
2166 /* geniCodeLogic- logic code */
2167 /*-----------------------------------------------------------------*/
2168 operand *geniCodeLogic (operand *left, operand *right, int op )
2172 link *rtype = operandType(right);
2173 link *ltype = operandType(left);
2175 /* left is integral type and right is literal then
2176 check if the literal value is within bounds */
2177 if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2178 int nbits = bitsForType(ltype);
2179 long v = operandLitValue(right);
2181 if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2182 werror(W_CONST_RANGE," compare operation ");
2185 ctype = computeType(ltype,rtype);
2186 left = geniCodeCast(ctype,left,TRUE);
2187 right= geniCodeCast(ctype,right,TRUE);
2189 ic = newiCode(op,left,right);
2190 IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2192 /* if comparing anything greater than one byte
2193 and not a '==' || '!=' || '&&' || '||' (these
2195 if (getSize(ctype) > 1 &&
2203 return IC_RESULT(ic);
2206 /*-----------------------------------------------------------------*/
2207 /* geniCodeUnary - for a a generic unary operation */
2208 /*-----------------------------------------------------------------*/
2209 operand *geniCodeUnary (operand *op, int oper )
2211 iCode *ic = newiCode (oper,op,NULL);
2213 IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2215 return IC_RESULT(ic) ;
2218 /*-----------------------------------------------------------------*/
2219 /* geniCodeConditional - geniCode for '?' ':' operation */
2220 /*-----------------------------------------------------------------*/
2221 operand *geniCodeConditional (ast *tree)
2224 symbol *falseLabel = newiTempLabel(NULL);
2225 symbol *exitLabel = newiTempLabel(NULL);
2226 operand *cond = ast2iCode(tree->left);
2227 operand *true, *false , *result;
2229 ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2233 true = ast2iCode(tree->right->left);
2235 /* move the value to a new Operand */
2236 result = newiTempOperand(operandType(true),0);
2237 geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2239 /* generate an unconditional goto */
2240 geniCodeGoto(exitLabel);
2242 /* now for the right side */
2243 geniCodeLabel(falseLabel);
2245 false = ast2iCode(tree->right->right);
2246 geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2248 /* create the exit label */
2249 geniCodeLabel(exitLabel);
2254 /*-----------------------------------------------------------------*/
2255 /* geniCodeAssign - generate code for assignment */
2256 /*-----------------------------------------------------------------*/
2257 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2260 link *ltype = operandType(left);
2261 link *rtype = operandType(right);
2263 if (!left->isaddr && !IS_ITEMP(left)) {
2264 werror(E_LVALUE_REQUIRED,"assignment");
2268 /* left is integral type and right is literal then
2269 check if the literal value is within bounds */
2270 if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2271 int nbits = bitsForType(ltype);
2272 long v = operandLitValue(right);
2274 if (v > ((LONG_LONG)1 << nbits) && v > 0)
2275 werror(W_CONST_RANGE," = operation");
2277 /* if the left & right type don't exactly match */
2278 /* if pointer set then make sure the check is
2279 done with the type & not the pointer */
2280 /* then cast rights type to left */
2282 /* first check the type for pointer assignement */
2283 if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2284 checkType(ltype,rtype)<0) {
2285 if (checkType(ltype->next,rtype) < 0)
2286 right = geniCodeCast(ltype->next,right,TRUE);
2288 if (checkType(ltype,rtype) < 0 )
2289 right = geniCodeCast(ltype,right,TRUE);
2291 /* if left is a true symbol & ! volatile
2292 create an assignment to temporary for
2293 the right & then assign this temporary
2294 to the symbol this is SSA . isn't it simple
2295 and folks have published mountains of paper on it */
2296 if (IS_TRUE_SYMOP(left) &&
2297 !isOperandVolatile(left,FALSE) &&
2298 isOperandGlobal(left)) {
2301 if (IS_TRUE_SYMOP(right))
2302 sym = OP_SYMBOL(right);
2303 ic = newiCode('=',NULL,right);
2304 IC_RESULT(ic) = right = newiTempOperand(ltype,0);
2305 SPIL_LOC(right) = sym ;
2309 ic = newiCode('=',NULL,right);
2310 IC_RESULT(ic) = left;
2313 /* if left isgptr flag is set then support
2314 routine will be required */
2318 ic->nosupdate = nosupdate;
2322 /*-----------------------------------------------------------------*/
2323 /* geniCodeSEParms - generate code for side effecting fcalls */
2324 /*-----------------------------------------------------------------*/
2325 static void geniCodeSEParms (ast *parms)
2330 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2331 geniCodeSEParms (parms->left) ;
2332 geniCodeSEParms (parms->right);
2336 /* hack don't like this but too lazy to think of
2338 if (IS_ADDRESS_OF_OP(parms))
2339 parms->left->lvalue = 1;
2341 if (IS_CAST_OP(parms) &&
2342 IS_PTR(parms->ftype) &&
2343 IS_ADDRESS_OF_OP(parms->right))
2344 parms->right->left->lvalue = 1;
2346 parms->opval.oprnd =
2347 geniCodeRValue(ast2iCode (parms),FALSE);
2349 parms->type = EX_OPERAND ;
2352 /*-----------------------------------------------------------------*/
2353 /* geniCodeParms - generates parameters */
2354 /*-----------------------------------------------------------------*/
2355 static void geniCodeParms ( ast *parms , int *stack, link *fetype)
2363 /* if this is a param node then do the left & right */
2364 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2365 geniCodeParms (parms->left, stack,fetype) ;
2366 geniCodeParms (parms->right, stack,fetype);
2370 /* get the parameter value */
2371 if (parms->type == EX_OPERAND)
2372 pval = parms->opval.oprnd ;
2374 /* maybe this else should go away ?? */
2375 /* hack don't like this but too lazy to think of
2377 if (IS_ADDRESS_OF_OP(parms))
2378 parms->left->lvalue = 1;
2380 if (IS_CAST_OP(parms) &&
2381 IS_PTR(parms->ftype) &&
2382 IS_ADDRESS_OF_OP(parms->right))
2383 parms->right->left->lvalue = 1;
2385 pval = geniCodeRValue(ast2iCode (parms),FALSE);
2388 /* if register parm then make it a send */
2389 if ((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2390 IS_REGPARM(parms->etype)) {
2391 ic = newiCode(SEND,pval,NULL);
2394 /* now decide whether to push or assign */
2395 if (!(options.stackAuto || IS_RENT(fetype))) {
2398 operand *top = operandFromSymbol(parms->argSym);
2399 geniCodeAssign(top,pval,1);
2402 link *p = operandType(pval);
2404 ic = newiCode(IPUSH,pval,NULL);
2406 /* update the stack adjustment */
2407 *stack += getSize(IS_AGGREGATE(p)? aggrToPtr(p,FALSE):p);
2414 /*-----------------------------------------------------------------*/
2415 /* geniCodeCall - generates temp code for calling */
2416 /*-----------------------------------------------------------------*/
2417 operand *geniCodeCall (operand *left, ast *parms)
2424 /* take care of parameters with side-effecting
2425 function calls in them, this is required to take care
2426 of overlaying function parameters */
2427 geniCodeSEParms ( parms );
2429 /* first the parameters */
2430 geniCodeParms ( parms , &stack , getSpec(operandType(left)));
2432 /* now call : if symbol then pcall */
2434 ic = newiCode(PCALL,left,NULL);
2436 ic = newiCode(CALL,left,NULL);
2438 IC_ARGS(ic) = left->operand.symOperand->args ;
2439 type = copyLinkChain(operandType(left)->next);
2440 etype = getSpec(type);
2441 SPEC_EXTR(etype) = 0;
2442 IC_RESULT(ic) = result = newiTempOperand(type,1);
2446 /* stack adjustment after call */
2447 left->parmBytes = stack;
2452 /*-----------------------------------------------------------------*/
2453 /* geniCodeReceive - generate intermediate code for "receive" */
2454 /*-----------------------------------------------------------------*/
2455 static void geniCodeReceive (value *args)
2457 /* for all arguments that are passed in registers */
2460 if (IS_REGPARM(args->etype)) {
2461 operand *opr = operandFromValue(args);
2463 symbol *sym = OP_SYMBOL(opr);
2466 /* we will use it after all optimizations
2467 and before liveRange calculation */
2468 if (!sym->addrtaken &&
2469 !IS_VOLATILE(sym->etype) &&
2470 !IN_FARSPACE(SPEC_OCLS(sym->etype))) {
2471 opl = newiTempOperand(args->type,0);
2473 sym->reqv->key = sym->key ;
2474 OP_SYMBOL(sym->reqv)->key = sym->key;
2475 OP_SYMBOL(sym->reqv)->isreqv = 1;
2476 OP_SYMBOL(sym->reqv)->islocal= 0;
2477 SPIL_LOC(sym->reqv) = sym;
2480 ic = newiCode(RECEIVE,NULL,NULL);
2481 currFunc->recvSize = getSize(sym->etype);
2482 IC_RESULT(ic) = opr;
2490 /*-----------------------------------------------------------------*/
2491 /* geniCodeFunctionBody - create the function body */
2492 /*-----------------------------------------------------------------*/
2493 void geniCodeFunctionBody (ast *tree)
2500 /* reset the auto generation */
2506 func = ast2iCode(tree->left);
2507 fetype = getSpec(operandType(func));
2509 savelineno = lineno;
2510 lineno = OP_SYMBOL(func)->lineDef;
2511 /* create an entry label */
2512 geniCodeLabel(entryLabel);
2513 lineno = savelineno;
2515 /* create a proc icode */
2516 ic = newiCode(FUNCTION,func,NULL);
2517 /* if the function has parmas then */
2518 /* save the parameters information */
2519 ic->argLabel.args = tree->values.args ;
2520 ic->lineno = OP_SYMBOL(func)->lineDef;
2524 /* for all parameters that are passed
2525 on registers add a "receive" */
2526 geniCodeReceive( tree->values.args );
2528 /* generate code for the body */
2529 ast2iCode(tree->right);
2531 /* create a label for return */
2532 geniCodeLabel(returnLabel);
2534 /* now generate the end proc */
2535 ic = newiCode(ENDFUNCTION,func,NULL);
2540 /*-----------------------------------------------------------------*/
2541 /* geniCodeReturn - gen icode for 'return' statement */
2542 /*-----------------------------------------------------------------*/
2543 void geniCodeReturn (operand *op)
2547 /* if the operand is present force an rvalue */
2549 op = geniCodeRValue(op,FALSE);
2551 ic = newiCode(RETURN,op,NULL);
2555 /*-----------------------------------------------------------------*/
2556 /* geniCodeIfx - generates code for extended if statement */
2557 /*-----------------------------------------------------------------*/
2558 void geniCodeIfx (ast *tree)
2561 operand *condition = ast2iCode(tree->left);
2564 /* if condition is null then exit */
2568 condition = geniCodeRValue(condition,FALSE);
2570 cetype = getSpec(operandType(condition));
2571 /* if the condition is a literal */
2572 if (IS_LITERAL(cetype)) {
2573 if (floatFromVal(condition->operand.valOperand)) {
2574 if (tree->trueLabel)
2575 geniCodeGoto(tree->trueLabel);
2580 if (tree->falseLabel)
2581 geniCodeGoto (tree->falseLabel);
2588 if ( tree->trueLabel ) {
2589 ic = newiCodeCondition(condition,
2594 if ( tree->falseLabel)
2595 geniCodeGoto(tree->falseLabel);
2598 ic = newiCodeCondition (condition,
2605 ast2iCode(tree->right);
2608 /*-----------------------------------------------------------------*/
2609 /* geniCodeJumpTable - tries to create a jump table for switch */
2610 /*-----------------------------------------------------------------*/
2611 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2613 int min = 0 ,max = 0, t, cnt = 0;
2618 set *labels = NULL ;
2620 if (!tree || !caseVals)
2623 /* the criteria for creating a jump table is */
2624 /* all integer numbers between the maximum & minimum must */
2625 /* be present , the maximum value should not exceed 255 */
2626 min = max = (int)floatFromVal(vch = caseVals);
2627 sprintf(buffer,"_case_%d_%d",
2628 tree->values.switchVals.swNum,
2630 addSet(&labels,newiTempLabel(buffer));
2632 /* if there is only one case value then no need */
2633 if (!(vch = vch->next ))
2637 if (((t = (int)floatFromVal(vch)) - max) != 1)
2639 sprintf(buffer,"_case_%d_%d",
2640 tree->values.switchVals.swNum,
2642 addSet(&labels,newiTempLabel(buffer));
2648 /* if the number of case statements <= 2 then */
2649 /* it is not economical to create the jump table */
2650 /* since two compares are needed for boundary conditions */
2651 if ((! optimize.noJTabBoundary && cnt <= 2) || max > (255/3))
2654 if ( tree->values.switchVals.swDefault )
2655 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2657 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2659 falseLabel = newiTempLabel (buffer);
2661 /* so we can create a jumptable */
2662 /* first we rule out the boundary conditions */
2663 /* if only optimization says so */
2664 if ( ! optimize.noJTabBoundary ) {
2665 link *cetype = getSpec(operandType(cond));
2666 /* no need to check the lower bound if
2667 the condition is unsigned & minimum value is zero */
2668 if (!( min == 0 && SPEC_USIGN(cetype))) {
2669 boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2670 ic = newiCodeCondition (boundary,falseLabel,NULL);
2674 /* now for upper bounds */
2675 boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2676 ic = newiCodeCondition (boundary,falseLabel,NULL);
2680 /* if the min is not zero then we no make it zero */
2682 cond = geniCodeSubtract(cond,operandFromLit(min));
2683 setOperandType(cond, UCHARTYPE);
2686 /* now create the jumptable */
2687 ic = newiCode(JUMPTABLE,NULL,NULL);
2688 IC_JTCOND(ic) = cond;
2689 IC_JTLABELS(ic) = labels;
2694 /*-----------------------------------------------------------------*/
2695 /* geniCodeSwitch - changes a switch to a if statement */
2696 /*-----------------------------------------------------------------*/
2697 void geniCodeSwitch (ast *tree)
2700 operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2701 value *caseVals = tree->values.switchVals.swVals ;
2702 symbol *trueLabel , *falseLabel;
2704 /* if we can make this a jump table */
2705 if ( geniCodeJumpTable (cond,caseVals,tree) )
2706 goto jumpTable ; /* no need for the comparison */
2708 /* for the cases defined do */
2711 operand *compare = geniCodeLogic (cond,
2712 operandFromValue(caseVals),
2715 sprintf(buffer,"_case_%d_%d",
2716 tree->values.switchVals.swNum,
2717 (int) floatFromVal(caseVals));
2718 trueLabel = newiTempLabel(buffer);
2720 ic = newiCodeCondition(compare,trueLabel,NULL);
2722 caseVals = caseVals->next;
2727 /* if default is present then goto break else break */
2728 if ( tree->values.switchVals.swDefault )
2729 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2731 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2733 falseLabel = newiTempLabel (buffer);
2734 geniCodeGoto(falseLabel);
2737 ast2iCode(tree->right);
2740 /*-----------------------------------------------------------------*/
2741 /* geniCodeInline - intermediate code for inline assembler */
2742 /*-----------------------------------------------------------------*/
2743 static void geniCodeInline (ast *tree)
2747 ic = newiCode(INLINEASM,NULL,NULL);
2748 IC_INLINE(ic) = tree->values.inlineasm;
2752 /*-----------------------------------------------------------------*/
2753 /* ast2iCode - creates an icodeList from an ast */
2754 /*-----------------------------------------------------------------*/
2755 operand *ast2iCode (ast *tree)
2757 operand *left = NULL;
2758 operand *right= NULL;
2763 /* set the global variables for filename & line number */
2764 if ( tree->filename )
2765 filename = tree->filename ;
2767 lineno = tree->lineno ;
2769 block = tree->block ;
2771 scopeLevel = tree->level;
2773 if (tree->type == EX_VALUE )
2774 return operandFromValue(tree->opval.val);
2776 if (tree->type == EX_LINK )
2777 return operandFromLink (tree->opval.lnk);
2779 /* if we find a nullop */
2780 if (tree->type == EX_OP &&
2781 ( tree->opval.op == NULLOP ||
2782 tree->opval.op == BLOCK )) {
2783 ast2iCode (tree->left);
2784 ast2iCode (tree->right);
2788 /* special cases for not evaluating */
2789 if ( tree->opval.op != ':' &&
2790 tree->opval.op != '?' &&
2791 tree->opval.op != CALL &&
2792 tree->opval.op != IFX &&
2793 tree->opval.op != LABEL &&
2794 tree->opval.op != GOTO &&
2795 tree->opval.op != SWITCH &&
2796 tree->opval.op != FUNCTION &&
2797 tree->opval.op != INLINEASM ) {
2798 if (IS_ASSIGN_OP(tree->opval.op) ||
2799 IS_DEREF_OP(tree) ||
2800 (tree->opval.op == '&' && !tree->right) ||
2801 tree->opval.op == PTR_OP) {
2803 left = operandFromAst(tree->left);
2806 left = operandFromAst(tree->left);
2808 if (tree->opval.op == INC_OP ||
2809 tree->opval.op == DEC_OP) {
2811 right= operandFromAst(tree->right);
2814 right= operandFromAst(tree->right);
2818 /* now depending on the type of operand */
2819 /* this will be a biggy */
2820 switch (tree->opval.op) {
2822 case '[' : /* array operation */
2823 left= geniCodeRValue (left,FALSE);
2824 right=geniCodeRValue (right,TRUE);
2826 return geniCodeArray (left,right);
2828 case '.' : /* structure dereference */
2829 if (IS_PTR(operandType(left)))
2830 left = geniCodeRValue(left,TRUE);
2832 left = geniCodeRValue(left,FALSE);
2834 return geniCodeStruct (left,right,tree->lvalue);
2836 case PTR_OP: /* structure pointer dereference */
2839 pType = operandType(left);
2840 left = geniCodeRValue(left,TRUE);
2842 setOClass (pType,getSpec(operandType(left)));
2845 return geniCodeStruct (left, right,tree->lvalue);
2847 case INC_OP: /* increment operator */
2849 return geniCodePostInc (left);
2851 return geniCodePreInc (right);
2853 case DEC_OP: /* decrement operator */
2855 return geniCodePostDec (left);
2857 return geniCodePreDec (right);
2859 case '&' : /* bitwise and or address of operator */
2860 if ( right ) { /* this is a bitwise operator */
2861 left= geniCodeRValue(left,FALSE);
2862 right= geniCodeRValue(right,FALSE);
2863 return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
2865 return geniCodeAddressOf (left);
2867 case '|': /* bitwise or & xor */
2869 return geniCodeBitwise (geniCodeRValue(left,FALSE),
2870 geniCodeRValue(right,FALSE),
2875 return geniCodeDivision (geniCodeRValue(left,FALSE),
2876 geniCodeRValue(right,FALSE));
2879 return geniCodeModulus (geniCodeRValue(left,FALSE),
2880 geniCodeRValue(right,FALSE));
2883 return geniCodeMultiply (geniCodeRValue(left,FALSE),
2884 geniCodeRValue(right,FALSE));
2886 return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
2890 return geniCodeSubtract (geniCodeRValue(left,FALSE),
2891 geniCodeRValue(right,FALSE));
2893 return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
2897 return geniCodeAdd (geniCodeRValue(left,FALSE),
2898 geniCodeRValue(right,FALSE));
2900 return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
2903 return geniCodeLeftShift (geniCodeRValue(left,FALSE),
2904 geniCodeRValue(right,FALSE));
2907 return geniCodeRightShift (geniCodeRValue(left,FALSE),
2908 geniCodeRValue(right,FALSE));
2910 return geniCodeCast (operandType(left),
2911 geniCodeRValue(right,FALSE),FALSE);
2917 return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2921 operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2922 setOperandType(op, UCHARTYPE);
2933 return geniCodeLogic (geniCodeRValue(left,FALSE),
2934 geniCodeRValue(right,FALSE),
2937 return geniCodeConditional (tree);
2940 return operandFromLit(getSize(tree->right->ftype));
2944 link *rtype = operandType(right);
2945 link *ltype = operandType(left);
2946 if (IS_PTR(rtype) && IS_ITEMP(right)
2947 && right->isaddr && checkType(rtype->next,ltype)==1)
2948 right = geniCodeRValue(right,TRUE);
2950 right = geniCodeRValue(right,FALSE);
2952 geniCodeAssign (left,right,0);
2957 geniCodeAssign(left,
2958 geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
2960 geniCodeRValue(right,FALSE)),0);
2964 geniCodeAssign(left,
2965 geniCodeDivision(geniCodeRValue(operandFromOperand(left),
2967 geniCodeRValue(right,FALSE)),0);
2970 geniCodeAssign(left,
2971 geniCodeModulus(geniCodeRValue(operandFromOperand(left),
2973 geniCodeRValue(right,FALSE)),0);
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);
2982 right = geniCodeRValue(right,FALSE);
2985 return geniCodeAssign(left,
2986 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
2992 link *rtype = operandType(right);
2993 link *ltype = operandType(left);
2994 if (IS_PTR(rtype) && IS_ITEMP(right)
2995 && right->isaddr && checkType(rtype->next,ltype)==1) {
2996 right = geniCodeRValue(right,TRUE);
2999 right = geniCodeRValue(right,FALSE);
3002 geniCodeAssign (left,
3003 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
3009 geniCodeAssign (left,
3010 geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
3012 geniCodeRValue(right,FALSE)),0);
3015 geniCodeAssign(left,
3016 geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
3018 geniCodeRValue(right,FALSE)),0);
3021 geniCodeAssign (left,
3022 geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
3024 geniCodeRValue(right,FALSE),
3026 operandType(left)),0);
3029 geniCodeAssign (left,
3030 geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3032 geniCodeRValue(right,FALSE),
3034 operandType(left)),0);
3037 geniCodeAssign (left,
3038 geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3040 geniCodeRValue(right,FALSE),
3042 operandType(left)),0);
3044 return geniCodeRValue(right,FALSE);
3047 return geniCodeCall (ast2iCode(tree->left),
3050 geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3051 return ast2iCode (tree->right);
3054 geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3055 return ast2iCode (tree->right);
3058 geniCodeFunctionBody ( tree );
3062 geniCodeReturn (right);
3070 geniCodeSwitch (tree);
3074 geniCodeInline (tree);
3081 /*-----------------------------------------------------------------*/
3082 /* reverseICChain - gets from the list and creates a linkedlist */
3083 /*-----------------------------------------------------------------*/
3084 iCode *reverseiCChain ()
3086 iCode *loop = NULL ;
3087 iCode *prev = NULL ;
3089 while ((loop = getSet(&iCodeChain))) {
3100 /*-----------------------------------------------------------------*/
3101 /* iCodeFromAst - given an ast will convert it to iCode */
3102 /*-----------------------------------------------------------------*/
3103 iCode *iCodeFromAst ( ast *tree )
3105 returnLabel = newiTempLabel("_return");
3106 entryLabel = newiTempLabel("_entry") ;
3108 return reverseiCChain ();