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 ;
41 symbol *returnLabel ; /* function return label */
42 symbol *entryLabel ; /* function entry label */
43 /*-----------------------------------------------------------------*/
44 /* forward definition of some functions */
45 operand *geniCodeDivision (operand *,operand *);
46 operand *geniCodeAssign (operand *,operand *,int);
47 operand *geniCodeArray (operand *,operand *);
48 operand *geniCodeArray2Ptr (operand *);
49 operand *geniCodeRValue (operand *, bool );
50 operand *geniCodeDerefPtr (operand *);
52 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
53 /* forward definition of print functions */
54 PRINTFUNC(picGetValueAtAddr);
55 PRINTFUNC(picSetValueAtAddr);
57 PRINTFUNC(picGeneric);
58 PRINTFUNC(picGenericOne);
64 PRINTFUNC(picJumpTable);
66 PRINTFUNC(picReceive);
68 iCodeTable codeTable[] = {
69 { '!' , "not", picGenericOne , NULL },
70 { '~' , "~" , picGenericOne , NULL },
71 { RRC , "rrc", picGenericOne , NULL },
72 { RLC , "rlc", picGenericOne , NULL },
73 { GETHBIT ,"ghbit", picGenericOne , NULL },
74 { UNARYMINUS , "-" , picGenericOne , NULL },
75 { IPUSH , "push",picGenericOne , NULL },
76 { IPOP , "pop", picGenericOne , NULL },
77 { CALL , "call",picGenericOne , NULL },
78 { PCALL , "pcall",picGenericOne , NULL },
79 { FUNCTION , "proc", picGenericOne , NULL },
80 { ENDFUNCTION ,"eproc", picGenericOne , NULL },
81 { RETURN , "ret", picGenericOne , NULL },
82 { '+' , "+" , picGeneric , NULL },
83 { '-' , "-" , picGeneric , NULL },
84 { '*' , "*" , picGeneric , NULL },
85 { '/' , "/" , picGeneric , NULL },
86 { '%' , "%" , picGeneric , NULL },
87 { '>' , ">" , picGeneric , NULL },
88 { '<' , "<" , picGeneric , NULL },
89 { LE_OP , "<=" , picGeneric , NULL },
90 { GE_OP , ">=" , picGeneric , NULL },
91 { EQ_OP , "==" , picGeneric , NULL },
92 { NE_OP , "!=" , picGeneric , NULL },
93 { AND_OP , "&&" , picGeneric , NULL },
94 { OR_OP , "||" , picGeneric , NULL },
95 { '^' , "^" , picGeneric , NULL },
96 { '|' , "|" , picGeneric , NULL },
97 { BITWISEAND , "&" , picGeneric , NULL },
98 { LEFT_OP , "<<" , picGeneric , NULL },
99 { RIGHT_OP , ">>" , picGeneric , NULL },
100 { GET_VALUE_AT_ADDRESS, "@" , picGetValueAtAddr, NULL },
101 { ADDRESS_OF , "&" , picAddrOf , NULL },
102 { CAST , "<>" , picCast , NULL },
103 { '=' , ":=" , picAssign , NULL },
104 { LABEL , "" , picLabel , NULL },
105 { GOTO , "" , picGoto , NULL },
106 { JUMPTABLE ,"jtab" , picJumpTable , NULL },
107 { IFX , "if" , picIfx , NULL },
108 { INLINEASM , "" , picInline , NULL },
109 { RECEIVE , "recv", picReceive , NULL },
110 { SEND , "send", picGenericOne , NULL }
114 /*-----------------------------------------------------------------*/
115 /* operandName - returns the name of the operand */
116 /*-----------------------------------------------------------------*/
117 int printOperand (operand *op, FILE *file)
132 opetype = getSpec (operandType(op));
133 if (SPEC_NOUN(opetype) == V_FLOAT)
134 fprintf (file,"%g {", SPEC_CVAL(opetype).v_float);
136 fprintf (file,"0x%x {",(int) floatFromVal(op->operand.valOperand));
137 printTypeChain(operandType(op),file);
144 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}" ,*/
145 (OP_SYMBOL(op)->rname[0] ? OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name),
147 OP_LIVEFROM(op),OP_LIVETO(op),
148 OP_SYMBOL(op)->stack,
149 op->isaddr, OP_SYMBOL(op)->isreqv,OP_SYMBOL(op)->remat
152 fprintf(file,"{"); printTypeChain(operandType(op),file);
153 if (SPIL_LOC(op) && IS_ITEMP(op))
154 fprintf(file,"}{ sir@ %s",SPIL_LOC(op)->rname);
159 /* if assigned to registers */
160 if (OP_SYMBOL(op)->nRegs) {
161 if (OP_SYMBOL(op)->isspilt) {
162 if (!OP_SYMBOL(op)->remat)
163 if (OP_SYMBOL(op)->usl.spillLoc)
164 fprintf(file,"[%s]",(OP_SYMBOL(op)->usl.spillLoc->rname[0] ?
165 OP_SYMBOL(op)->usl.spillLoc->rname :
166 OP_SYMBOL(op)->usl.spillLoc->name));
168 fprintf(file,"[err]");
170 fprintf(file,"[remat]");
175 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
176 fprintf(file,"%s ", port->getRegName(OP_SYMBOL(op)->regs[i]));
181 fprintf(file,"%s",(OP_SYMBOL(op)->rname[0] ?
182 OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name));
183 /* if assigned to registers */
184 if (OP_SYMBOL(op)->nRegs && !OP_SYMBOL(op)->isspilt) {
187 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
188 fprintf(file,"%s ",(OP_SYMBOL(op)->regs[i] ?
189 OP_SYMBOL(op)->regs[i]->name :
198 printTypeChain(op->operand.typeOperand,file);
209 /*-----------------------------------------------------------------*/
210 /* print functions */
211 /*-----------------------------------------------------------------*/
212 PRINTFUNC(picGetValueAtAddr)
215 printOperand (IC_RESULT(ic),of);
218 printOperand (IC_LEFT(ic), of);
224 PRINTFUNC(picSetValueAtAddr)
228 printOperand(IC_LEFT(ic),of);
230 printOperand(IC_RIGHT(ic),of);
237 printOperand(IC_RESULT(ic),of);
238 if (IS_ITEMP(IC_LEFT(ic)))
242 printOperand(IC_LEFT(ic),of);
244 if (IS_ITEMP(IC_LEFT(ic)))
245 fprintf(of," offsetAdd ");
248 printOperand(IC_RIGHT(ic),of);
250 if (IS_ITEMP(IC_LEFT(ic)))
256 PRINTFUNC(picJumpTable)
261 fprintf(of,"%s\t",s);
262 printOperand(IC_JTCOND(ic),of);
264 for ( sym = setFirstItem(IC_JTLABELS(ic)); sym;
265 sym = setNextItem(IC_JTLABELS(ic)))
266 fprintf(of,"\t\t\t%s\n",sym->name);
269 PRINTFUNC(picGeneric)
272 printOperand(IC_RESULT(ic),of);
274 printOperand(IC_LEFT(ic),of);
275 fprintf(of," %s ",s);
276 printOperand(IC_RIGHT(ic),of);
280 PRINTFUNC(picGenericOne)
283 if ( IC_RESULT(ic) ) {
284 printOperand(IC_RESULT(ic),of);
289 fprintf (of,"%s ",s);
290 printOperand(IC_LEFT(ic),of);
293 if (! IC_RESULT(ic) && !IC_LEFT(ic))
302 printOperand(IC_RESULT(ic),of);
304 printOperand(IC_LEFT(ic),of);
305 printOperand(IC_RIGHT(ic),of);
314 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
317 printOperand(IC_RESULT(ic),of);
319 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
322 fprintf(of," %s ", s);
323 printOperand (IC_RIGHT(ic),of);
330 fprintf(of," %s($%d) :\n",IC_LABEL(ic)->name,IC_LABEL(ic)->key);
336 fprintf (of," goto %s($%d)\n", IC_LABEL(ic)->name,IC_LABEL(ic)->key);
343 printOperand(IC_COND(ic),of);
346 fprintf (of," == 0 goto %s($%d)\n",IC_FALSE(ic)->name,IC_FALSE(ic)->key);
348 fprintf (of," != 0 goto %s($%d)\n",IC_TRUE(ic)->name,IC_TRUE(ic)->key);
350 fprintf (of,"\tzzgoto %s\n",IC_FALSE(ic)->name);
356 fprintf(of,"%s",IC_INLINE(ic));
359 PRINTFUNC(picReceive)
361 printOperand(IC_RESULT(ic),of);
362 fprintf(of," = %s ",s);
363 printOperand(IC_LEFT(ic),of);
367 /*-----------------------------------------------------------------*/
368 /* piCode - prints one iCode */
369 /*-----------------------------------------------------------------*/
370 int piCode (void *item, FILE *of)
378 icTab = getTableEntry(ic->op) ;
379 fprintf(stdout,"%s(%d:%d:%d:%d:%d)\t",
380 ic->filename,ic->lineno,
381 ic->seq,ic->key,ic->depth,ic->supportRtn);
382 icTab->iCodePrint(of,ic,icTab->printName);
386 /*-----------------------------------------------------------------*/
387 /* printiCChain - prints intermediate code for humans */
388 /*-----------------------------------------------------------------*/
389 void printiCChain (iCode *icChain, FILE *of)
396 for ( loop = icChain ; loop ; loop = loop->next ) {
397 if ((icTab = getTableEntry (loop->op ))) {
398 fprintf(of,"%s(%d:%d:%d:%d:%d)\t",
399 loop->filename,loop->lineno,
400 loop->seq,loop->key,loop->depth,loop->supportRtn);
402 icTab->iCodePrint (of,loop,icTab->printName);
408 /*-----------------------------------------------------------------*/
409 /* newOperand - allocate, init & return a new iCode */
410 /*-----------------------------------------------------------------*/
411 operand *newOperand ()
415 ALLOC(op,sizeof(operand));
421 /*-----------------------------------------------------------------*/
422 /* newiCode - create and return a new iCode entry initialised */
423 /*-----------------------------------------------------------------*/
424 iCode *newiCode (int op, operand *left, operand *right)
428 ALLOC(ic,sizeof(iCode));
430 ic->lineno = lineno ;
431 ic->filename= filename ;
433 ic->level = scopeLevel;
435 ic->key= iCodeKey++ ;
442 /*-----------------------------------------------------------------*/
443 /* newiCode for conditional statements */
444 /*-----------------------------------------------------------------*/
445 iCode *newiCodeCondition (operand *condition,
451 ic = newiCode(IFX,NULL,NULL);
452 IC_COND(ic) = condition ;
453 IC_TRUE(ic) = trueLabel ;
454 IC_FALSE(ic) = falseLabel;
458 /*-----------------------------------------------------------------*/
459 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
460 /*-----------------------------------------------------------------*/
461 iCode *newiCodeLabelGoto (int op, symbol *label)
465 ic = newiCode(op,NULL,NULL);
467 ic->argLabel.label = label ;
469 IC_RIGHT(ic) = NULL ;
470 IC_RESULT(ic) = NULL ;
474 /*-----------------------------------------------------------------*/
475 /* newiTemp - allocate & return a newItemp Variable */
476 /*-----------------------------------------------------------------*/
477 symbol *newiTemp (char *s)
482 sprintf(buffer,"%s",s);
484 sprintf (buffer,"iTemp%d",iTempNum++);
485 itmp = newSymbol (buffer,1);
486 strcpy(itmp->rname,itmp->name);
492 /*-----------------------------------------------------------------*/
493 /* newiTempLabel - creates a temp variable label */
494 /*-----------------------------------------------------------------*/
495 symbol *newiTempLabel (char *s)
499 /* check if this alredy exists */
500 if (s && (itmplbl = findSym(LabelTab, NULL, s)))
504 itmplbl = newSymbol(s,1);
506 sprintf(buffer,"iTempLbl%d",iTempLblNum++);
507 itmplbl = newSymbol(buffer,1);
512 itmplbl->key = labelKey++ ;
513 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
517 /*-----------------------------------------------------------------*/
518 /* newiTempPreheaderLabel - creates a new preheader label */
519 /*-----------------------------------------------------------------*/
520 symbol *newiTempPreheaderLabel()
524 sprintf(buffer,"preHeaderLbl%d",iTempLblNum++);
525 itmplbl = newSymbol(buffer,1);
529 itmplbl->key = labelKey++ ;
530 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
535 /*-----------------------------------------------------------------*/
536 /* initiCode - initialises some iCode related stuff */
537 /*-----------------------------------------------------------------*/
543 /*-----------------------------------------------------------------*/
544 /* copyiCode - make a copy of the iCode given */
545 /*-----------------------------------------------------------------*/
546 iCode *copyiCode (iCode *ic)
548 iCode *nic = newiCode(ic->op,NULL,NULL);
550 nic->lineno = ic->lineno ;
551 nic->filename= ic->filename ;
552 nic->block = ic->block;
553 nic->level = ic->level;
555 /* deal with the special cases first */
558 IC_COND(nic) = operandFromOperand(IC_COND(ic));
559 IC_TRUE(nic) = IC_TRUE(ic);
560 IC_FALSE(nic)= IC_FALSE(ic);
564 IC_JTCOND(nic) = operandFromOperand(IC_JTCOND(ic));
565 IC_JTLABELS(nic) = IC_JTLABELS(ic);
570 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
571 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
572 IC_ARGS(nic) = IC_ARGS(ic);
576 IC_INLINE(nic) = IC_INLINE(ic);
580 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
581 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
582 IC_RIGHT(nic)= operandFromOperand(IC_RIGHT(ic));
588 /*-----------------------------------------------------------------*/
589 /* getTableEntry - gets the table entry for the given operator */
590 /*-----------------------------------------------------------------*/
591 iCodeTable *getTableEntry (int oper )
595 for ( i = 0 ; i < (sizeof(codeTable)/sizeof(iCodeTable)); i++ )
596 if (oper == codeTable[i].icode)
597 return &codeTable[i] ;
602 /*-----------------------------------------------------------------*/
603 /* newiTempOperand - new intermediate temp operand */
604 /*-----------------------------------------------------------------*/
605 operand *newiTempOperand (sym_link *type, char throwType)
608 operand *op = newOperand();
612 itmp = newiTemp(NULL);
614 etype = getSpec(type);
616 if (IS_LITERAL(etype) )
619 /* copy the type information */
621 itmp->etype = getSpec (itmp->type = (throwType ? type :
622 copyLinkChain(type)));
623 if (IS_LITERAL(itmp->etype)) {
624 SPEC_SCLS(itmp->etype) = S_REGISTER ;
625 SPEC_OCLS(itmp->etype) = reg;
628 op->operand.symOperand = itmp;
629 op->key = itmp->key = ++operandKey ;
633 /*-----------------------------------------------------------------*/
634 /* operandType - returns the type chain for an operand */
635 /*-----------------------------------------------------------------*/
636 sym_link *operandType (operand *op)
638 /* depending on type of operand */
642 return op->operand.valOperand->type ;
645 return op->operand.symOperand->type ;
648 return op->operand.typeOperand ;
650 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
651 " operand type not known ");
652 assert (0) ; /* should never come here */
653 /* Just to keep the compiler happy */
654 return (sym_link *)0;
658 /*-----------------------------------------------------------------*/
659 /* isParamterToCall - will return 1 if op is a parameter to args */
660 /*-----------------------------------------------------------------*/
661 int isParameterToCall (value *args, operand *op)
667 isSymbolEqual(op->operand.symOperand,tval->sym))
674 /*-----------------------------------------------------------------*/
675 /* isOperandGlobal - return 1 if operand is a global variable */
676 /*-----------------------------------------------------------------*/
677 int isOperandGlobal ( operand *op )
685 if (op->type == SYMBOL &&
686 (op->operand.symOperand->level == 0 ||
687 IS_STATIC(op->operand.symOperand->etype) ||
688 IS_EXTERN(op->operand.symOperand->etype))
695 /*-----------------------------------------------------------------*/
696 /* isOperandVolatile - return 1 if the operand is volatile */
697 /*-----------------------------------------------------------------*/
698 int isOperandVolatile ( operand *op , bool chkTemp)
703 if (IS_ITEMP(op) && !chkTemp)
706 opetype = getSpec(optype = operandType(op));
708 if (IS_PTR(optype) && DCL_PTR_VOLATILE(optype))
711 if (IS_VOLATILE(opetype))
716 /*-----------------------------------------------------------------*/
717 /* isOperandLiteral - returns 1 if an operand contains a literal */
718 /*-----------------------------------------------------------------*/
719 int isOperandLiteral ( operand *op )
726 opetype = getSpec (operandType(op));
728 if (IS_LITERAL(opetype))
733 /*-----------------------------------------------------------------*/
734 /* isOperandInFarSpace - will return true if operand is in farSpace*/
735 /*-----------------------------------------------------------------*/
736 bool isOperandInFarSpace (operand *op)
746 if (!IS_TRUE_SYMOP(op)) {
748 etype = SPIL_LOC(op)->etype;
754 etype = getSpec(operandType(op));
756 return (IN_FARSPACE(SPEC_OCLS(etype)) ? TRUE : FALSE);
759 /*-----------------------------------------------------------------*/
760 /* isOperandOnStack - will return true if operand is on stack */
761 /*-----------------------------------------------------------------*/
762 bool isOperandOnStack(operand *op)
772 etype = getSpec(operandType(op));
774 return ((IN_STACK(etype)) ? TRUE : FALSE);
777 /*-----------------------------------------------------------------*/
778 /* operandLitValue - literal value of an operand */
779 /*-----------------------------------------------------------------*/
780 double operandLitValue ( operand *op )
782 assert(isOperandLiteral(op));
784 return floatFromVal(op->operand.valOperand);
787 /*-----------------------------------------------------------------*/
788 /* operandOperation - perforoms operations on operands */
789 /*-----------------------------------------------------------------*/
790 operand *operandOperation (operand *left,operand *right,
791 int op, sym_link *type)
793 operand *retval = (operand *)0;
795 assert(isOperandLiteral(left));
797 assert(isOperandLiteral(right));
801 retval = operandFromValue (valCastLiteral(type,
802 operandLitValue(left) +
803 operandLitValue(right)));
806 retval = operandFromValue(valCastLiteral(type,
807 operandLitValue(left) -
808 operandLitValue(right)));
811 retval = operandFromValue(valCastLiteral(type,
812 operandLitValue(left) *
813 operandLitValue(right)));
816 if ((unsigned long) operandLitValue(right) == 0){
817 werror(E_DIVIDE_BY_ZERO);
822 retval = operandFromValue (valCastLiteral(type,
823 operandLitValue(left) /
824 operandLitValue(right)));
827 if ((unsigned long) operandLitValue(right) == 0){
828 werror(E_DIVIDE_BY_ZERO);
832 retval = operandFromLit ((unsigned long) operandLitValue(left) %
833 (unsigned long) operandLitValue(right));
836 retval = operandFromLit ((unsigned long) operandLitValue(left) <<
837 (unsigned long) operandLitValue(right));
840 retval = operandFromLit ((unsigned long) operandLitValue(left) >>
841 (unsigned long) 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 (operandLitValue(left) !=
857 operandLitValue(right));
860 retval = operandFromLit (operandLitValue(left) >
861 operandLitValue(right));
864 retval = operandFromLit (operandLitValue(left) >=
865 operandLitValue(right));
868 retval = operandFromLit ((unsigned long) operandLitValue(left) &
869 (unsigned long) operandLitValue(right));
872 retval = operandFromLit ((unsigned long) operandLitValue(left) |
873 (unsigned long) operandLitValue(right));
876 retval = operandFromLit ((unsigned long) operandLitValue(left) ^
877 (unsigned long) operandLitValue(right));
880 retval = operandFromLit (operandLitValue(left) &&
881 operandLitValue(right));
884 retval = operandFromLit (operandLitValue(left) ||
885 operandLitValue(right));
889 long i = operandLitValue(left);
891 retval = operandFromLit ((i >> (getSize(operandType(left))*8 - 1)) |
897 long i = operandLitValue(left);
899 retval = operandFromLit ((i << (getSize(operandType(left))*8 - 1)) |
905 retval = operandFromLit(-1 * operandLitValue(left));
909 retval = operandFromLit(~ ((long) operandLitValue(left)));
913 retval = operandFromLit(! operandLitValue(left));
917 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
918 " operandOperation invalid operator ");
926 /*-----------------------------------------------------------------*/
927 /* isOperandEqual - compares two operand & return 1 if they r = */
928 /*-----------------------------------------------------------------*/
929 int isOperandEqual (operand *left, operand *right)
931 /* if the pointers are equal then they are equal */
935 /* if either of them null then false */
936 if ( !left || !right)
939 if (left->type != right->type)
942 if (IS_SYMOP(left) && IS_SYMOP(right))
943 return left->key == right->key ;
945 /* if types are the same */
946 switch (left->type) {
948 return isSymbolEqual(left->operand.symOperand,
949 right->operand.symOperand);
951 return (floatFromVal(left->operand.valOperand) ==
952 floatFromVal(right->operand.valOperand));
954 if (checkType(left->operand.typeOperand,
955 right->operand.typeOperand) == 1)
962 /*-----------------------------------------------------------------*/
963 /* isiCodeEqual - comapres two iCodes are returns true if yes */
964 /*-----------------------------------------------------------------*/
965 int isiCodeEqual (iCode *left, iCode *right)
967 /* if the same pointer */
971 /* if either of them null */
975 /* if operand are the same */
976 if ( left->op == right->op ) {
978 /* compare all the elements depending on type */
979 if (left->op != IFX ) {
980 if (!isOperandEqual(IC_LEFT(left),IC_LEFT(right)))
982 if (!isOperandEqual(IC_RIGHT(left),IC_RIGHT(right)))
986 if (!isOperandEqual(IC_COND(left),IC_COND(right)))
988 if (!isSymbolEqual (IC_TRUE(left),IC_TRUE(right)))
990 if (!isSymbolEqual(IC_FALSE(left),IC_FALSE(right)))
998 /*-----------------------------------------------------------------*/
999 /* newiTempFromOp - create a temp Operand with same attributes */
1000 /*-----------------------------------------------------------------*/
1001 operand *newiTempFromOp (operand *op)
1011 nop = newiTempOperand(operandType(op),TRUE);
1012 nop->isaddr = op->isaddr ;
1013 nop->isvolatile = op->isvolatile ;
1014 nop->isGlobal = op->isGlobal ;
1015 nop->isLiteral= op->isLiteral ;
1016 nop->noSpilLoc= op->noSpilLoc;
1017 nop->usesDefs = op->usesDefs;
1018 nop->isParm = op->isParm;
1019 nop->parmBytes = op->parmBytes;
1023 /*-----------------------------------------------------------------*/
1024 /* operand from operand - creates an operand holder for the type */
1025 /*-----------------------------------------------------------------*/
1026 operand *operandFromOperand (operand *op)
1033 nop->type = op->type;
1034 nop->isaddr = op->isaddr ;
1035 nop->key = op->key ;
1036 nop->isvolatile = op->isvolatile ;
1037 nop->isGlobal = op->isGlobal ;
1038 nop->isLiteral= op->isLiteral ;
1039 nop->noSpilLoc= op->noSpilLoc;
1040 nop->usesDefs = op->usesDefs;
1041 nop->isParm = op->isParm;
1042 nop->parmBytes = op->parmBytes;
1044 switch (nop->type) {
1046 nop->operand.symOperand = op->operand.symOperand ;
1049 nop->operand.valOperand = op->operand.valOperand;
1052 nop->operand.typeOperand = op->operand.typeOperand ;
1059 /*-----------------------------------------------------------------*/
1060 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1061 /*-----------------------------------------------------------------*/
1062 operand *opFromOpWithDU (operand *op, bitVect *defs, bitVect *uses)
1064 operand *nop = operandFromOperand(op);
1066 if (nop->type == SYMBOL) {
1067 OP_SYMBOL(nop)->defs = bitVectCopy(defs);
1068 OP_SYMBOL(nop)->uses = bitVectCopy(uses);
1074 /*-----------------------------------------------------------------*/
1075 /* operandFromSymbol - creates an operand from a symbol */
1076 /*-----------------------------------------------------------------*/
1077 operand *operandFromSymbol (symbol *sym)
1082 /* if the symbol's type is a literal */
1083 /* then it is an enumerator type */
1084 if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype))
1085 return operandFromValue (valFromType(sym->etype));
1088 sym->key = ++operandKey ;
1090 /* if this an implicit variable, means struct/union */
1091 /* member so just return it */
1092 if (sym->implicit || IS_FUNC(sym->type)) {
1095 op->operand.symOperand = sym;
1096 op->key = sym->key ;
1097 op->isvolatile = isOperandVolatile(op,TRUE);
1098 op->isGlobal = isOperandGlobal(op);
1099 op->parmBytes = sym->argStack;
1103 /* under the following conditions create a
1104 register equivalent for a local symbol */
1105 if (sym->level && sym->etype && SPEC_OCLS(sym->etype) &&
1106 (IN_FARSPACE(SPEC_OCLS(sym->etype)) && (!IS_DS390_PORT)) &&
1107 options.stackAuto == 0)
1110 if (!IS_AGGREGATE(sym->type) && /* not an aggregate */
1111 !IS_FUNC(sym->type) && /* not a function */
1112 !sym->_isparm && /* not a parameter */
1113 sym->level && /* is a local variable */
1114 !sym->addrtaken && /* whose address has not been taken */
1115 !sym->reqv && /* does not already have a register euivalence */
1116 !IS_VOLATILE(sym->etype) && /* not declared as volatile */
1117 !IS_STATIC(sym->etype) && /* and not declared static */
1118 !sym->islbl && /* not a label */
1119 ok && /* farspace check */
1120 !IS_BITVAR(sym->etype) /* not a bit variable */
1123 /* we will use it after all optimizations
1124 and before liveRange calculation */
1125 sym->reqv = newiTempOperand(sym->type,0);
1126 sym->reqv->key = sym->key ;
1127 OP_SYMBOL(sym->reqv)->key = sym->key;
1128 OP_SYMBOL(sym->reqv)->isreqv = 1;
1129 OP_SYMBOL(sym->reqv)->islocal = 1;
1130 SPIL_LOC(sym->reqv) = sym;
1133 if (!IS_AGGREGATE(sym->type)) {
1136 op->operand.symOperand = sym;
1139 op->isvolatile = isOperandVolatile(op,TRUE);
1140 op->isGlobal = isOperandGlobal(op);
1141 op->isPtr = IS_PTR(operandType(op));
1142 op->isParm = sym->_isparm ;
1147 /* itemp = &[_symbol] */
1149 ic = newiCode(ADDRESS_OF,newOperand(),NULL);
1150 IC_LEFT(ic)->type = SYMBOL ;
1151 IC_LEFT(ic)->operand.symOperand = sym ;
1152 IC_LEFT(ic)->key = sym->key;
1153 (IC_LEFT(ic))->isvolatile = isOperandVolatile(IC_LEFT(ic),TRUE);
1154 (IC_LEFT(ic))->isGlobal = isOperandGlobal(IC_LEFT(ic));
1155 IC_LEFT(ic)->isPtr = IS_PTR(operandType(IC_LEFT(ic)));
1158 IC_RESULT(ic) = newiTempOperand(sym->type,0);
1159 if (IS_ARRAY(sym->type)) {
1160 IC_RESULT(ic) = geniCodeArray2Ptr (IC_RESULT(ic));
1161 IC_RESULT(ic)->isaddr = 0;
1163 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(sym->type));
1165 IC_RESULT(ic)->operand.symOperand->args = sym->args;
1169 return IC_RESULT(ic) ;
1172 /*-----------------------------------------------------------------*/
1173 /* operandFromValue - creates an operand from value */
1174 /*-----------------------------------------------------------------*/
1175 operand *operandFromValue (value *val)
1179 /* if this is a symbol then do the symbol thing */
1181 return operandFromSymbol (val->sym);
1183 /* this is not a symbol */
1186 op->operand.valOperand = val ;
1187 op->isLiteral = isOperandLiteral(op);
1191 /*-----------------------------------------------------------------*/
1192 /* operandFromLink - operand from typeChain */
1193 /*-----------------------------------------------------------------*/
1194 operand *operandFromLink (sym_link *type)
1198 /* operand from sym_link */
1204 op->operand.typeOperand = copyLinkChain(type);
1208 /*-----------------------------------------------------------------*/
1209 /* operandFromLit - makes an operand from a literal value */
1210 /*-----------------------------------------------------------------*/
1211 operand *operandFromLit ( float i)
1213 return operandFromValue (valueFromLit (i));
1216 /*-----------------------------------------------------------------*/
1217 /* operandFromAst - creates an operand from an ast */
1218 /*-----------------------------------------------------------------*/
1219 operand *operandFromAst ( ast *tree )
1225 /* depending on type do */
1226 switch (tree->type ) {
1228 return ast2iCode (tree) ;
1232 return operandFromValue(tree->opval.val) ;
1236 return operandFromLink (tree->opval.lnk) ;
1240 /* Just to keep the comiler happy */
1241 return (operand *)0;
1244 /*-----------------------------------------------------------------*/
1245 /* setOperandType - sets the operand's type to the given type */
1246 /*-----------------------------------------------------------------*/
1247 void setOperandType (operand *op, sym_link *type)
1249 /* depending on the type of operand */
1253 op->operand.valOperand->etype =
1254 getSpec( op->operand.valOperand->type =
1255 copyLinkChain (type )) ;
1259 if (op->operand.symOperand->isitmp )
1260 op->operand.symOperand->etype =
1261 getSpec( op->operand.symOperand->type =
1262 copyLinkChain (type )) ;
1264 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
1265 "attempt to modify type of source");
1269 op->operand.typeOperand = copyLinkChain (type);
1275 /*-----------------------------------------------------------------*/
1276 /* geniCodeValueAtAddress - generate intermeditate code for value */
1278 /*-----------------------------------------------------------------*/
1279 operand *geniCodeRValue (operand *op, bool force)
1282 sym_link *type = operandType(op);
1283 sym_link *etype= getSpec(type);
1285 /* if this is an array & already */
1286 /* an address then return this */
1287 if (IS_AGGREGATE(type) ||
1288 (IS_PTR(type) && !force && !op->isaddr))
1289 return operandFromOperand(op);
1291 /* if this is not an address then must be */
1292 /* rvalue already so return this one */
1296 /* if this is not a temp symbol then */
1297 if (!IS_ITEMP(op) &&
1299 !IN_FARSPACE(SPEC_OCLS(etype))) {
1300 op = operandFromOperand(op);
1305 if (IS_SPEC(type) &&
1306 IS_TRUE_SYMOP(op) &&
1307 !IN_FARSPACE(SPEC_OCLS(etype))) {
1308 op = operandFromOperand(op);
1313 ic = newiCode(GET_VALUE_AT_ADDRESS,op,NULL);
1314 if (IS_PTR(type) && op->isaddr && force)
1317 type = copyLinkChain(type);
1319 IC_RESULT(ic) = newiTempOperand (type,1);
1320 IC_RESULT(ic)->isaddr = 0;
1322 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1324 /* if the right is a symbol */
1325 if (op->type == SYMBOL)
1326 IC_RESULT(ic)->operand.symOperand->args =
1327 op->operand.symOperand->args ;
1330 return IC_RESULT(ic) ;
1333 /*-----------------------------------------------------------------*/
1334 /* geniCodeCast - changes the value from one type to another */
1335 /*-----------------------------------------------------------------*/
1336 operand *geniCodeCast (sym_link *type, operand *op, bool implicit)
1340 sym_link *opetype = getSpec(optype = operandType(op));
1343 /* one of them has size zero then error */
1344 if (IS_VOID(optype)) {
1345 werror(E_CAST_ZERO);
1349 /* if the operand is already the desired type then do nothing */
1350 if ( checkType (type,optype) == 1)
1353 /* if this is a literal then just change the type & return */
1354 if (IS_LITERAL(opetype) && op->type == VALUE && !IS_PTR(type) && !IS_PTR(optype))
1355 return operandFromValue(valCastLiteral(type,
1356 operandLitValue(op)));
1358 /* if casting to some pointer type &&
1359 the destination is not a generic pointer
1360 then give a warning : (only for implicit casts)*/
1361 if (IS_PTR(optype) && implicit &&
1362 (DCL_TYPE(optype) != DCL_TYPE(type)) &&
1364 werror(E_INCOMPAT_CAST);
1365 werror(E_CONTINUE,"from type '");
1366 printTypeChain(optype,stderr);fprintf(stderr,"' to type '");
1367 printTypeChain(type,stderr);fprintf(stderr,"'\n");
1370 /* if they are the same size create an assignment */
1371 if (getSize(type) == getSize(optype) &&
1372 !IS_BITFIELD(type) &&
1374 !IS_FLOAT(optype) &&
1375 ((IS_SPEC(type) && IS_SPEC(optype)) ||
1376 (!IS_SPEC(type) && !IS_SPEC(optype)))) {
1378 ic = newiCode('=',NULL,op);
1379 IC_RESULT(ic) = newiTempOperand(type,0);
1380 SPIL_LOC(IC_RESULT(ic)) =
1381 (IS_TRUE_SYMOP(op) ? OP_SYMBOL(op) : NULL);
1382 IC_RESULT(ic)->isaddr = 0;
1384 ic = newiCode(CAST,operandFromLink(type),
1385 geniCodeRValue(op,FALSE));
1387 IC_RESULT(ic)= newiTempOperand(type,0);
1390 /* preserve the storage class & output class */
1391 /* of the original variable */
1392 restype = getSpec(operandType(IC_RESULT(ic)));
1393 SPEC_SCLS(restype) = SPEC_SCLS(opetype);
1394 SPEC_OCLS(restype) = SPEC_OCLS(opetype);
1397 return IC_RESULT(ic) ;
1400 /*-----------------------------------------------------------------*/
1401 /* geniCodeLabel - will create a Label */
1402 /*-----------------------------------------------------------------*/
1403 void geniCodeLabel (symbol *label)
1407 ic = newiCodeLabelGoto(LABEL,label);
1411 /*-----------------------------------------------------------------*/
1412 /* geniCodeGoto - will create a Goto */
1413 /*-----------------------------------------------------------------*/
1414 void geniCodeGoto (symbol *label)
1418 ic = newiCodeLabelGoto(GOTO,label);
1422 /*-----------------------------------------------------------------*/
1423 /* geniCodeMultiply - gen intermediate code for multiplication */
1424 /*-----------------------------------------------------------------*/
1425 operand *geniCodeMultiply (operand *left, operand *right)
1432 /* if they are both literal then we know the result */
1433 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1434 return operandFromValue (valMult(left->operand.valOperand,
1435 right->operand.valOperand));
1437 resType = computeType (ltype,rtype) ;
1438 left = geniCodeCast(resType,left,TRUE);
1439 right= geniCodeCast(resType,right,TRUE);
1441 /* if the right is a literal & power of 2 */
1442 /* then make it a left shift */
1443 if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
1444 (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand))))
1445 ic = newiCode(LEFT_OP, left,operandFromLit(p2)); /* left shift */
1447 ic = newiCode('*',left,right); /* normal multiplication */
1448 /* if the size left or right > 1 then support routine */
1449 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1453 IC_RESULT(ic) = newiTempOperand(resType,1);
1456 return IC_RESULT(ic) ;
1459 /*-----------------------------------------------------------------*/
1460 /* geniCodeDivision - gen intermediate code for division */
1461 /*-----------------------------------------------------------------*/
1462 operand *geniCodeDivision (operand *left, operand *right)
1467 sym_link *rtype = operandType(right);
1468 sym_link *retype= getSpec(rtype);
1469 sym_link *ltype = operandType(left);
1470 sym_link *letype= getSpec(ltype);
1472 resType = computeType (ltype,rtype) ;
1473 left = geniCodeCast(resType,left,TRUE);
1474 right= geniCodeCast(resType,right,TRUE);
1476 /* if the right is a literal & power of 2 */
1477 /* then make it a right shift */
1478 if (IS_LITERAL(retype) &&
1479 !IS_FLOAT(letype) &&
1480 (p2 = powof2 ((unsigned long)
1481 floatFromVal(right->operand.valOperand))))
1482 ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
1484 ic = newiCode('/',left,right); /* normal division */
1485 /* if the size left or right > 1 then support routine */
1486 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1489 IC_RESULT(ic) = newiTempOperand(resType,0);
1492 return IC_RESULT(ic) ;
1494 /*-----------------------------------------------------------------*/
1495 /* geniCodeModulus - gen intermediate code for modulus */
1496 /*-----------------------------------------------------------------*/
1497 operand *geniCodeModulus (operand *left, operand *right)
1503 /* if they are both literal then we know the result */
1504 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1505 return operandFromValue (valMod(left->operand.valOperand,
1506 right->operand.valOperand));
1508 resType = computeType (ltype,rtype) ;
1509 left = geniCodeCast(resType,left,TRUE);
1510 right= geniCodeCast(resType,right,TRUE);
1512 /* now they are the same size */
1513 ic = newiCode('%',left,right);
1515 /* if the size left or right > 1 then support routine */
1516 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1518 IC_RESULT(ic) = newiTempOperand(resType,0);
1521 return IC_RESULT(ic) ;
1524 /*-----------------------------------------------------------------*/
1525 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1526 /*-----------------------------------------------------------------*/
1527 operand *geniCodePtrPtrSubtract (operand *left, operand *right)
1533 /* if they are both literals then */
1534 if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
1535 result = operandFromValue (valMinus(left->operand.valOperand,
1536 right->operand.valOperand));
1540 ic = newiCode('-',left,right);
1542 IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
1546 return geniCodeDivision (result,
1547 operandFromLit(getSize(ltype->next)));
1550 /*-----------------------------------------------------------------*/
1551 /* geniCodeSubtract - generates code for subtraction */
1552 /*-----------------------------------------------------------------*/
1553 operand *geniCodeSubtract (operand *left, operand *right)
1560 /* if they both pointers then */
1561 if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
1562 (IS_PTR(rtype) || IS_ARRAY(rtype)))
1563 return geniCodePtrPtrSubtract (left,right);
1565 /* if they are both literal then we know the result */
1566 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1567 && left->isLiteral && right->isLiteral)
1568 return operandFromValue (valMinus(left->operand.valOperand,
1569 right->operand.valOperand));
1571 /* if left is an array or pointer */
1572 if ( IS_PTR(ltype) || IS_ARRAY(ltype) ) {
1573 isarray = left->isaddr ;
1574 right = geniCodeMultiply (right,
1575 operandFromLit(getSize(ltype->next)));
1576 resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
1578 else { /* make them the same size */
1579 resType = computeType (ltype,rtype) ;
1580 left = geniCodeCast(resType,left,TRUE);
1581 right= geniCodeCast(resType,right,TRUE);
1584 ic = newiCode('-',left,right);
1586 IC_RESULT(ic)= newiTempOperand(resType,1);
1587 IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
1589 /* if left or right is a float */
1590 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1594 return IC_RESULT(ic) ;
1597 /*-----------------------------------------------------------------*/
1598 /* geniCodeAdd - generates iCode for addition */
1599 /*-----------------------------------------------------------------*/
1600 operand *geniCodeAdd (operand *left, operand *right )
1608 /* if left is an array then array access */
1609 if (IS_ARRAY(ltype))
1610 return geniCodeArray (left,right);
1612 /* if the right side is LITERAL zero */
1613 /* return the left side */
1614 if (IS_LITERAL(retype) && right->isLiteral && !floatFromVal(valFromType(retype)))
1617 /* if left is literal zero return right */
1618 if (IS_LITERAL(letype) && left->isLiteral && !floatFromVal(valFromType(letype)))
1621 /* if left is an array or pointer then size */
1622 if (IS_PTR(ltype)) {
1624 isarray = left->isaddr;
1626 operandFromLit(getSize(ltype->next));
1627 if (getSize(ltype) > 1 && (getSize(rtype) < INTSIZE))
1629 right = geniCodeCast(INTTYPE,right,TRUE);
1631 right = geniCodeMultiply (right ,size);
1633 resType = copyLinkChain(ltype);
1635 else { /* make them the same size */
1636 resType = computeType (ltype,rtype) ;
1637 left = geniCodeCast(resType,left,TRUE);
1638 right= geniCodeCast(resType,right,TRUE);
1641 /* if they are both literals then we know */
1642 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1643 && left->isLiteral && right->isLiteral)
1644 return operandFromValue (valPlus(valFromType(letype),
1645 valFromType(retype)));
1647 ic = newiCode('+',left,right);
1649 IC_RESULT(ic) = newiTempOperand(resType,1);
1650 IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
1652 /* if left or right is a float then support
1654 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1659 return IC_RESULT(ic) ;
1663 /*-----------------------------------------------------------------*/
1664 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1665 /*-----------------------------------------------------------------*/
1666 sym_link *aggrToPtr ( sym_link *type, bool force)
1672 if (IS_PTR(type) && !force)
1675 etype = getSpec(type);
1679 /* if the output class is generic */
1680 if ((DCL_TYPE(ptype) = PTR_TYPE(SPEC_OCLS(etype))) == CPOINTER)
1681 DCL_PTR_CONST(ptype) = port->mem.code_ro;
1683 /* if the variable was declared a constant */
1684 /* then the pointer points to a constant */
1685 if (IS_CONSTANT(etype) )
1686 DCL_PTR_CONST(ptype) = 1;
1688 /* the variable was volatile then pointer to volatile */
1689 if (IS_VOLATILE(etype))
1690 DCL_PTR_VOLATILE(ptype) = 1;
1694 /*-----------------------------------------------------------------*/
1695 /* geniCodeArray2Ptr - array to pointer */
1696 /*-----------------------------------------------------------------*/
1697 operand *geniCodeArray2Ptr (operand *op)
1699 sym_link *optype = operandType(op);
1700 sym_link *opetype = getSpec(optype);
1702 /* set the pointer depending on the storage class */
1703 if ((DCL_TYPE(optype) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1704 DCL_PTR_CONST(optype) = port->mem.code_ro;
1707 /* if the variable was declared a constant */
1708 /* then the pointer points to a constant */
1709 if (IS_CONSTANT(opetype) )
1710 DCL_PTR_CONST(optype) = 1;
1712 /* the variable was volatile then pointer to volatile */
1713 if (IS_VOLATILE(opetype))
1714 DCL_PTR_VOLATILE(optype) = 1;
1719 /*-----------------------------------------------------------------*/
1720 /* geniCodeArray - array access */
1721 /*-----------------------------------------------------------------*/
1722 operand *geniCodeArray (operand *left,operand *right)
1725 sym_link *ltype = operandType(left);
1727 if (IS_PTR(ltype)) {
1728 if (IS_PTR(ltype->next) && left->isaddr)
1730 left = geniCodeRValue(left,FALSE);
1732 return geniCodeDerefPtr(geniCodeAdd(left,right));
1736 if (getSize(operandType(right)) < INTSIZE)
1738 /* Widen the index type to int first. */
1739 right = geniCodeCast(INTTYPE,right,TRUE);
1741 right = geniCodeMultiply(right,
1742 operandFromLit(getSize(ltype->next)));
1744 /* we can check for limits here */
1745 if (isOperandLiteral(right) &&
1748 (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
1749 werror(E_ARRAY_BOUND);
1750 right = operandFromLit(0);
1753 ic = newiCode('+',left,right);
1755 IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) &&
1756 !IS_AGGREGATE(ltype->next) &&
1757 !IS_PTR(ltype->next))
1758 ? ltype : ltype->next),0);
1760 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
1762 return IC_RESULT(ic) ;
1765 /*-----------------------------------------------------------------*/
1766 /* geniCodeStruct - generates intermediate code for structres */
1767 /*-----------------------------------------------------------------*/
1768 operand *geniCodeStruct (operand *left, operand *right, bool islval)
1771 sym_link *type = operandType(left);
1772 sym_link *etype = getSpec(type);
1774 symbol *element = getStructElement(SPEC_STRUCT(etype),
1775 right->operand.symOperand);
1777 /* add the offset */
1778 ic = newiCode('+',left,operandFromLit(element->offset));
1780 IC_RESULT(ic) = newiTempOperand(element->type,0);
1782 /* preserve the storage & output class of the struct */
1783 /* as well as the volatile attribute */
1784 retype = getSpec(operandType(IC_RESULT(ic)));
1785 SPEC_SCLS(retype) = SPEC_SCLS(etype);
1786 SPEC_OCLS(retype) = SPEC_OCLS(etype);
1787 SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);
1789 if (IS_PTR(element->type))
1790 setOperandType(IC_RESULT(ic),aggrToPtr(operandType(IC_RESULT(ic)),TRUE));
1792 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(element->type));
1796 return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
1799 /*-----------------------------------------------------------------*/
1800 /* geniCodePostInc - generate int code for Post increment */
1801 /*-----------------------------------------------------------------*/
1802 operand *geniCodePostInc (operand *op)
1806 sym_link *optype = operandType(op);
1808 operand *rv = (IS_ITEMP(op) ?
1809 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1811 sym_link *rvtype = operandType(rv);
1814 /* if this is not an address we have trouble */
1815 if ( ! op->isaddr ) {
1816 werror (E_LVALUE_REQUIRED,"++");
1820 rOp = newiTempOperand(rvtype,0);
1826 geniCodeAssign(rOp,rv,0);
1828 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1829 ic = newiCode('+',rv,operandFromLit(size));
1830 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1833 geniCodeAssign(op,result,0);
1839 /*-----------------------------------------------------------------*/
1840 /* geniCodePreInc - generate code for preIncrement */
1841 /*-----------------------------------------------------------------*/
1842 operand *geniCodePreInc (operand *op)
1845 sym_link *optype = operandType(op);
1846 operand *rop = (IS_ITEMP(op) ?
1847 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1849 sym_link *roptype = operandType(rop);
1853 if ( ! op->isaddr ) {
1854 werror(E_LVALUE_REQUIRED,"++");
1859 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1860 ic = newiCode('+',rop,operandFromLit(size));
1861 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1865 return geniCodeAssign(op,result,0) ;
1868 /*-----------------------------------------------------------------*/
1869 /* geniCodePostDec - generates code for Post decrement */
1870 /*-----------------------------------------------------------------*/
1871 operand *geniCodePostDec (operand *op)
1875 sym_link *optype = operandType(op);
1877 operand *rv = (IS_ITEMP(op) ?
1878 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1880 sym_link *rvtype = operandType(rv);
1883 /* if this is not an address we have trouble */
1884 if ( ! op->isaddr ) {
1885 werror (E_LVALUE_REQUIRED,"++");
1889 rOp = newiTempOperand(rvtype,0);
1895 geniCodeAssign(rOp,rv,0);
1897 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1898 ic = newiCode('-',rv,operandFromLit(size));
1899 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1902 geniCodeAssign(op,result,0);
1908 /*-----------------------------------------------------------------*/
1909 /* geniCodePreDec - generate code for pre decrement */
1910 /*-----------------------------------------------------------------*/
1911 operand *geniCodePreDec (operand *op)
1914 sym_link *optype = operandType(op);
1915 operand *rop = (IS_ITEMP(op) ?
1916 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1918 sym_link *roptype = operandType(rop);
1922 if ( ! op->isaddr ) {
1923 werror(E_LVALUE_REQUIRED,"++");
1928 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1929 ic = newiCode('-',rop,operandFromLit(size));
1930 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1934 return geniCodeAssign(op,result,0) ;
1938 /*-----------------------------------------------------------------*/
1939 /* geniCodeBitwise - gen int code for bitWise operators */
1940 /*-----------------------------------------------------------------*/
1941 operand *geniCodeBitwise (operand *left, operand *right,
1942 int oper, sym_link *resType)
1946 left = geniCodeCast(resType,left,TRUE);
1947 right= geniCodeCast(resType,right,TRUE);
1949 ic = newiCode(oper,left,right);
1950 IC_RESULT(ic) = newiTempOperand(resType,0);
1953 return IC_RESULT(ic) ;
1956 /*-----------------------------------------------------------------*/
1957 /* geniCodeAddressOf - gens icode for '&' address of operator */
1958 /*-----------------------------------------------------------------*/
1959 operand *geniCodeAddressOf (operand *op)
1963 sym_link *optype = operandType(op);
1964 sym_link *opetype= getSpec(optype);
1966 /* lvalue check already done in decorateType */
1967 /* this must be a lvalue */
1968 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
1969 /* werror (E_LVALUE_REQUIRED,"&"); */
1974 p->class = DECLARATOR ;
1976 /* set the pointer depending on the storage class */
1977 if ((DCL_TYPE(p) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1978 DCL_PTR_CONST(p) = port->mem.code_ro;
1980 /* make sure we preserve the const & volatile */
1981 if (IS_CONSTANT(opetype))
1982 DCL_PTR_CONST(p) = 1;
1984 if (IS_VOLATILE(opetype))
1985 DCL_PTR_VOLATILE(p) = 1;
1987 p->next = copyLinkChain(optype);
1989 /* if already a temp */
1991 setOperandType (op,p);
1996 /* other wise make this of the type coming in */
1997 ic = newiCode(ADDRESS_OF,op,NULL);
1998 IC_RESULT(ic) = newiTempOperand(p,1);
1999 IC_RESULT(ic)->isaddr = 0;
2001 return IC_RESULT(ic);
2003 /*-----------------------------------------------------------------*/
2004 /* setOClass - sets the output class depending on the pointer type */
2005 /*-----------------------------------------------------------------*/
2006 void setOClass (sym_link *ptr, sym_link *spec)
2008 switch (DCL_TYPE(ptr)) {
2010 SPEC_OCLS(spec) = data ;
2014 SPEC_OCLS(spec) = generic;
2018 SPEC_OCLS(spec) = xdata ;
2022 SPEC_OCLS(spec) = code ;
2026 SPEC_OCLS(spec) = idata;
2030 SPEC_OCLS(spec) = xstack;
2034 SPEC_OCLS(spec) = eeprom;
2043 /*-----------------------------------------------------------------*/
2044 /* geniCodeDerefPtr - dereference pointer with '*' */
2045 /*-----------------------------------------------------------------*/
2046 operand *geniCodeDerefPtr (operand *op)
2048 sym_link *rtype , *retype ;
2049 sym_link *optype = operandType(op);
2051 /* if this is a pointer then generate the rvalue */
2052 if (IS_PTR(optype)) {
2053 if (IS_TRUE_SYMOP(op)) {
2055 op = geniCodeRValue(op,TRUE);
2058 op = geniCodeRValue(op,TRUE);
2061 /* now get rid of the pointer part */
2062 if (lvaluereq && IS_ITEMP(op) )
2064 retype = getSpec(rtype = copyLinkChain(optype)) ;
2068 retype = getSpec(rtype = copyLinkChain(optype->next)) ;
2071 /* if this is a pointer then outputclass needs 2b updated */
2073 setOClass(optype,retype);
2075 op->isGptr = IS_GENPTR(optype);
2077 /* if the pointer was declared as a constant */
2078 /* then we cannot allow assignment to the derefed */
2079 if (IS_PTR_CONST(optype))
2080 SPEC_CONST(retype) = 1;
2082 op->isaddr = (IS_PTR(rtype) ||
2089 op = geniCodeRValue(op,TRUE);
2091 setOperandType(op,rtype);
2096 /*-----------------------------------------------------------------*/
2097 /* geniCodeUnaryMinus - does a unary minus of the operand */
2098 /*-----------------------------------------------------------------*/
2099 operand *geniCodeUnaryMinus (operand *op)
2102 sym_link *optype = operandType(op);
2104 if (IS_LITERAL(optype))
2105 return operandFromLit(- floatFromVal(op->operand.valOperand));
2107 ic = newiCode(UNARYMINUS,op,NULL);
2108 IC_RESULT(ic) = newiTempOperand(optype,0);
2110 return IC_RESULT(ic);
2113 /*-----------------------------------------------------------------*/
2114 /* geniCodeLeftShift - gen i code for left shift */
2115 /*-----------------------------------------------------------------*/
2116 operand *geniCodeLeftShift (operand *left, operand *right)
2119 sym_link *ltype = operandType(left);
2121 ic = newiCode(LEFT_OP,left,right);
2122 IC_RESULT(ic) = newiTempOperand(ltype,0);
2124 return IC_RESULT(ic) ;
2127 /*-----------------------------------------------------------------*/
2128 /* geniCodeRightShift - gen i code for right shift */
2129 /*-----------------------------------------------------------------*/
2130 operand *geniCodeRightShift (operand *left, operand *right)
2133 sym_link *ltype = operandType(left);
2135 ic = newiCode(RIGHT_OP,left,right);
2136 IC_RESULT(ic) = newiTempOperand(ltype,0);
2138 return IC_RESULT(ic) ;
2141 #if defined(__BORLANDC__) || defined(_MSC_VER)
2142 #define LONG_LONG __int64
2144 #define LONG_LONG long long
2147 /*-----------------------------------------------------------------*/
2148 /* geniCodeLogic- logic code */
2149 /*-----------------------------------------------------------------*/
2150 operand *geniCodeLogic (operand *left, operand *right, int op )
2154 sym_link *rtype = operandType(right);
2155 sym_link *ltype = operandType(left);
2157 /* left is integral type and right is literal then
2158 check if the literal value is within bounds */
2159 if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2160 int nbits = bitsForType(ltype);
2161 long v = operandLitValue(right);
2163 if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2164 werror(W_CONST_RANGE," compare operation ");
2167 ctype = computeType(ltype,rtype);
2168 left = geniCodeCast(ctype,left,TRUE);
2169 right= geniCodeCast(ctype,right,TRUE);
2171 ic = newiCode(op,left,right);
2172 IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2174 /* if comparing anything greater than one byte
2175 and not a '==' || '!=' || '&&' || '||' (these
2177 if (getSize(ctype) > 1 &&
2185 return IC_RESULT(ic);
2188 /*-----------------------------------------------------------------*/
2189 /* geniCodeUnary - for a a generic unary operation */
2190 /*-----------------------------------------------------------------*/
2191 operand *geniCodeUnary (operand *op, int oper )
2193 iCode *ic = newiCode (oper,op,NULL);
2195 IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2197 return IC_RESULT(ic) ;
2200 /*-----------------------------------------------------------------*/
2201 /* geniCodeConditional - geniCode for '?' ':' operation */
2202 /*-----------------------------------------------------------------*/
2203 operand *geniCodeConditional (ast *tree)
2206 symbol *falseLabel = newiTempLabel(NULL);
2207 symbol *exitLabel = newiTempLabel(NULL);
2208 operand *cond = ast2iCode(tree->left);
2209 operand *true, *false , *result;
2211 ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2215 true = ast2iCode(tree->right->left);
2217 /* move the value to a new Operand */
2218 result = newiTempOperand(operandType(true),0);
2219 geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2221 /* generate an unconditional goto */
2222 geniCodeGoto(exitLabel);
2224 /* now for the right side */
2225 geniCodeLabel(falseLabel);
2227 false = ast2iCode(tree->right->right);
2228 geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2230 /* create the exit label */
2231 geniCodeLabel(exitLabel);
2236 /*-----------------------------------------------------------------*/
2237 /* geniCodeAssign - generate code for assignment */
2238 /*-----------------------------------------------------------------*/
2239 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2242 sym_link *ltype = operandType(left);
2243 sym_link *rtype = operandType(right);
2245 if (!left->isaddr && !IS_ITEMP(left)) {
2246 werror(E_LVALUE_REQUIRED,"assignment");
2250 /* left is integral type and right is literal then
2251 check if the literal value is within bounds */
2252 if (IS_INTEGRAL(ltype) && right->type == VALUE && IS_LITERAL(rtype)) {
2253 int nbits = bitsForType(ltype);
2254 long v = operandLitValue(right);
2256 if (v > ((LONG_LONG)1 << nbits) && v > 0)
2257 werror(W_CONST_RANGE," = operation");
2260 /* if the left & right type don't exactly match */
2261 /* if pointer set then make sure the check is
2262 done with the type & not the pointer */
2263 /* then cast rights type to left */
2265 /* first check the type for pointer assignement */
2266 if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2267 checkType(ltype,rtype)<0) {
2268 if (checkType(ltype->next,rtype) < 0)
2269 right = geniCodeCast(ltype->next,right,TRUE);
2271 if (checkType(ltype,rtype) < 0 )
2272 right = geniCodeCast(ltype,right,TRUE);
2274 /* if left is a true symbol & ! volatile
2275 create an assignment to temporary for
2276 the right & then assign this temporary
2277 to the symbol this is SSA . isn't it simple
2278 and folks have published mountains of paper on it */
2279 if (IS_TRUE_SYMOP(left) &&
2280 !isOperandVolatile(left,FALSE) &&
2281 isOperandGlobal(left)) {
2284 if (IS_TRUE_SYMOP(right))
2285 sym = OP_SYMBOL(right);
2286 ic = newiCode('=',NULL,right);
2287 IC_RESULT(ic) = right = newiTempOperand(ltype,0);
2288 SPIL_LOC(right) = sym ;
2292 ic = newiCode('=',NULL,right);
2293 IC_RESULT(ic) = left;
2296 /* if left isgptr flag is set then support
2297 routine will be required */
2301 ic->nosupdate = nosupdate;
2305 /*-----------------------------------------------------------------*/
2306 /* geniCodeSEParms - generate code for side effecting fcalls */
2307 /*-----------------------------------------------------------------*/
2308 static void geniCodeSEParms (ast *parms)
2313 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2314 geniCodeSEParms (parms->left) ;
2315 geniCodeSEParms (parms->right);
2319 /* hack don't like this but too lazy to think of
2321 if (IS_ADDRESS_OF_OP(parms))
2322 parms->left->lvalue = 1;
2324 if (IS_CAST_OP(parms) &&
2325 IS_PTR(parms->ftype) &&
2326 IS_ADDRESS_OF_OP(parms->right))
2327 parms->right->left->lvalue = 1;
2329 parms->opval.oprnd =
2330 geniCodeRValue(ast2iCode (parms),FALSE);
2332 parms->type = EX_OPERAND ;
2335 /*-----------------------------------------------------------------*/
2336 /* geniCodeParms - generates parameters */
2337 /*-----------------------------------------------------------------*/
2338 static void geniCodeParms ( ast *parms , int *stack, sym_link *fetype, symbol *func)
2346 /* if this is a param node then do the left & right */
2347 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2348 geniCodeParms (parms->left, stack,fetype,func) ;
2349 geniCodeParms (parms->right, stack,fetype,func);
2353 /* get the parameter value */
2354 if (parms->type == EX_OPERAND)
2355 pval = parms->opval.oprnd ;
2357 /* maybe this else should go away ?? */
2358 /* hack don't like this but too lazy to think of
2360 if (IS_ADDRESS_OF_OP(parms))
2361 parms->left->lvalue = 1;
2363 if (IS_CAST_OP(parms) &&
2364 IS_PTR(parms->ftype) &&
2365 IS_ADDRESS_OF_OP(parms->right))
2366 parms->right->left->lvalue = 1;
2368 pval = geniCodeRValue(ast2iCode (parms),FALSE);
2371 /* if register parm then make it a send */
2372 if (((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2373 IS_REGPARM(parms->etype)) && !func->hasVargs ) {
2374 ic = newiCode(SEND,pval,NULL);
2377 /* now decide whether to push or assign */
2378 if (!(options.stackAuto || IS_RENT(fetype))) {
2381 operand *top = operandFromSymbol(parms->argSym);
2382 geniCodeAssign(top,pval,1);
2385 sym_link *p = operandType(pval);
2387 ic = newiCode(IPUSH,pval,NULL);
2389 /* update the stack adjustment */
2390 *stack += getSize(IS_AGGREGATE(p)? aggrToPtr(p,FALSE):p);
2397 /*-----------------------------------------------------------------*/
2398 /* geniCodeCall - generates temp code for calling */
2399 /*-----------------------------------------------------------------*/
2400 operand *geniCodeCall (operand *left, ast *parms)
2404 sym_link *type, *etype;
2407 /* take care of parameters with side-effecting
2408 function calls in them, this is required to take care
2409 of overlaying function parameters */
2410 geniCodeSEParms ( parms );
2412 /* first the parameters */
2413 geniCodeParms ( parms , &stack , getSpec(operandType(left)), OP_SYMBOL(left));
2415 /* now call : if symbol then pcall */
2417 ic = newiCode(PCALL,left,NULL);
2419 ic = newiCode(CALL,left,NULL);
2421 IC_ARGS(ic) = left->operand.symOperand->args ;
2422 type = copyLinkChain(operandType(left)->next);
2423 etype = getSpec(type);
2424 SPEC_EXTR(etype) = 0;
2425 IC_RESULT(ic) = result = newiTempOperand(type,1);
2429 /* stack adjustment after call */
2430 left->parmBytes = stack;
2435 /*-----------------------------------------------------------------*/
2436 /* geniCodeReceive - generate intermediate code for "receive" */
2437 /*-----------------------------------------------------------------*/
2438 static void geniCodeReceive (value *args)
2440 /* for all arguments that are passed in registers */
2443 if (IS_REGPARM(args->etype)) {
2444 operand *opr = operandFromValue(args);
2446 symbol *sym = OP_SYMBOL(opr);
2449 /* we will use it after all optimizations
2450 and before liveRange calculation */
2451 if (!sym->addrtaken && !IS_VOLATILE(sym->etype)) {
2453 if (IN_FARSPACE(SPEC_OCLS(sym->etype)) &&
2454 options.stackAuto == 0 &&
2457 opl = newiTempOperand(args->type,0);
2459 sym->reqv->key = sym->key ;
2460 OP_SYMBOL(sym->reqv)->key = sym->key;
2461 OP_SYMBOL(sym->reqv)->isreqv = 1;
2462 OP_SYMBOL(sym->reqv)->islocal= 0;
2463 SPIL_LOC(sym->reqv) = sym;
2467 ic = newiCode(RECEIVE,NULL,NULL);
2468 currFunc->recvSize = getSize(sym->etype);
2469 IC_RESULT(ic) = opr;
2477 /*-----------------------------------------------------------------*/
2478 /* geniCodeFunctionBody - create the function body */
2479 /*-----------------------------------------------------------------*/
2480 void geniCodeFunctionBody (ast *tree)
2487 /* reset the auto generation */
2493 func = ast2iCode(tree->left);
2494 fetype = getSpec(operandType(func));
2496 savelineno = lineno;
2497 lineno = OP_SYMBOL(func)->lineDef;
2498 /* create an entry label */
2499 geniCodeLabel(entryLabel);
2500 lineno = savelineno;
2502 /* create a proc icode */
2503 ic = newiCode(FUNCTION,func,NULL);
2504 /* if the function has parmas then */
2505 /* save the parameters information */
2506 ic->argLabel.args = tree->values.args ;
2507 ic->lineno = OP_SYMBOL(func)->lineDef;
2511 /* for all parameters that are passed
2512 on registers add a "receive" */
2513 geniCodeReceive( tree->values.args );
2515 /* generate code for the body */
2516 ast2iCode(tree->right);
2518 /* create a label for return */
2519 geniCodeLabel(returnLabel);
2521 /* now generate the end proc */
2522 ic = newiCode(ENDFUNCTION,func,NULL);
2527 /*-----------------------------------------------------------------*/
2528 /* geniCodeReturn - gen icode for 'return' statement */
2529 /*-----------------------------------------------------------------*/
2530 void geniCodeReturn (operand *op)
2534 /* if the operand is present force an rvalue */
2536 op = geniCodeRValue(op,FALSE);
2538 ic = newiCode(RETURN,op,NULL);
2542 /*-----------------------------------------------------------------*/
2543 /* geniCodeIfx - generates code for extended if statement */
2544 /*-----------------------------------------------------------------*/
2545 void geniCodeIfx (ast *tree)
2548 operand *condition = ast2iCode(tree->left);
2551 /* if condition is null then exit */
2555 condition = geniCodeRValue(condition,FALSE);
2557 cetype = getSpec(operandType(condition));
2558 /* if the condition is a literal */
2559 if (IS_LITERAL(cetype)) {
2560 if (floatFromVal(condition->operand.valOperand)) {
2561 if (tree->trueLabel)
2562 geniCodeGoto(tree->trueLabel);
2567 if (tree->falseLabel)
2568 geniCodeGoto (tree->falseLabel);
2575 if ( tree->trueLabel ) {
2576 ic = newiCodeCondition(condition,
2581 if ( tree->falseLabel)
2582 geniCodeGoto(tree->falseLabel);
2585 ic = newiCodeCondition (condition,
2592 ast2iCode(tree->right);
2595 /*-----------------------------------------------------------------*/
2596 /* geniCodeJumpTable - tries to create a jump table for switch */
2597 /*-----------------------------------------------------------------*/
2598 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2600 int min = 0 ,max = 0, t, cnt = 0;
2605 set *labels = NULL ;
2607 if (!tree || !caseVals)
2610 /* the criteria for creating a jump table is */
2611 /* all integer numbers between the maximum & minimum must */
2612 /* be present , the maximum value should not exceed 255 */
2613 min = max = (int)floatFromVal(vch = caseVals);
2614 sprintf(buffer,"_case_%d_%d",
2615 tree->values.switchVals.swNum,
2617 addSet(&labels,newiTempLabel(buffer));
2619 /* if there is only one case value then no need */
2620 if (!(vch = vch->next ))
2624 if (((t = (int)floatFromVal(vch)) - max) != 1)
2626 sprintf(buffer,"_case_%d_%d",
2627 tree->values.switchVals.swNum,
2629 addSet(&labels,newiTempLabel(buffer));
2635 /* if the number of case statements <= 2 then */
2636 /* it is not economical to create the jump table */
2637 /* since two compares are needed for boundary conditions */
2638 if ((! optimize.noJTabBoundary && cnt <= 2) || max > (255/3))
2641 if ( tree->values.switchVals.swDefault )
2642 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2644 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2646 falseLabel = newiTempLabel (buffer);
2648 /* so we can create a jumptable */
2649 /* first we rule out the boundary conditions */
2650 /* if only optimization says so */
2651 if ( ! optimize.noJTabBoundary ) {
2652 sym_link *cetype = getSpec(operandType(cond));
2653 /* no need to check the lower bound if
2654 the condition is unsigned & minimum value is zero */
2655 if (!( min == 0 && SPEC_USIGN(cetype))) {
2656 boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2657 ic = newiCodeCondition (boundary,falseLabel,NULL);
2661 /* now for upper bounds */
2662 boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2663 ic = newiCodeCondition (boundary,falseLabel,NULL);
2667 /* if the min is not zero then we no make it zero */
2669 cond = geniCodeSubtract(cond,operandFromLit(min));
2670 setOperandType(cond, UCHARTYPE);
2673 /* now create the jumptable */
2674 ic = newiCode(JUMPTABLE,NULL,NULL);
2675 IC_JTCOND(ic) = cond;
2676 IC_JTLABELS(ic) = labels;
2681 /*-----------------------------------------------------------------*/
2682 /* geniCodeSwitch - changes a switch to a if statement */
2683 /*-----------------------------------------------------------------*/
2684 void geniCodeSwitch (ast *tree)
2687 operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2688 value *caseVals = tree->values.switchVals.swVals ;
2689 symbol *trueLabel , *falseLabel;
2691 /* if we can make this a jump table */
2692 if ( geniCodeJumpTable (cond,caseVals,tree) )
2693 goto jumpTable ; /* no need for the comparison */
2695 /* for the cases defined do */
2698 operand *compare = geniCodeLogic (cond,
2699 operandFromValue(caseVals),
2702 sprintf(buffer,"_case_%d_%d",
2703 tree->values.switchVals.swNum,
2704 (int) floatFromVal(caseVals));
2705 trueLabel = newiTempLabel(buffer);
2707 ic = newiCodeCondition(compare,trueLabel,NULL);
2709 caseVals = caseVals->next;
2714 /* if default is present then goto break else break */
2715 if ( tree->values.switchVals.swDefault )
2716 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2718 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2720 falseLabel = newiTempLabel (buffer);
2721 geniCodeGoto(falseLabel);
2724 ast2iCode(tree->right);
2727 /*-----------------------------------------------------------------*/
2728 /* geniCodeInline - intermediate code for inline assembler */
2729 /*-----------------------------------------------------------------*/
2730 static void geniCodeInline (ast *tree)
2734 ic = newiCode(INLINEASM,NULL,NULL);
2735 IC_INLINE(ic) = tree->values.inlineasm;
2739 /*-----------------------------------------------------------------*/
2740 /* ast2iCode - creates an icodeList from an ast */
2741 /*-----------------------------------------------------------------*/
2742 operand *ast2iCode (ast *tree)
2744 operand *left = NULL;
2745 operand *right= NULL;
2750 /* set the global variables for filename & line number */
2751 if ( tree->filename )
2752 filename = tree->filename ;
2754 lineno = tree->lineno ;
2756 block = tree->block ;
2758 scopeLevel = tree->level;
2760 if (tree->type == EX_VALUE )
2761 return operandFromValue(tree->opval.val);
2763 if (tree->type == EX_LINK )
2764 return operandFromLink (tree->opval.lnk);
2766 /* if we find a nullop */
2767 if (tree->type == EX_OP &&
2768 ( tree->opval.op == NULLOP ||
2769 tree->opval.op == BLOCK )) {
2770 ast2iCode (tree->left);
2771 ast2iCode (tree->right);
2775 /* special cases for not evaluating */
2776 if ( tree->opval.op != ':' &&
2777 tree->opval.op != '?' &&
2778 tree->opval.op != CALL &&
2779 tree->opval.op != IFX &&
2780 tree->opval.op != LABEL &&
2781 tree->opval.op != GOTO &&
2782 tree->opval.op != SWITCH &&
2783 tree->opval.op != FUNCTION &&
2784 tree->opval.op != INLINEASM ) {
2786 if (IS_ASSIGN_OP(tree->opval.op) ||
2787 IS_DEREF_OP(tree) ||
2788 (tree->opval.op == '&' && !tree->right) ||
2789 tree->opval.op == PTR_OP) {
2791 if ((IS_ARRAY_OP(tree->left) && IS_ARRAY_OP(tree->left->left)) ||
2792 (IS_DEREF_OP(tree) && IS_ARRAY_OP(tree->left)))
2794 int olvr = lvaluereq ;
2796 left = operandFromAst(tree->left);
2797 lvaluereq = olvr - 1;
2799 left = operandFromAst(tree->left);
2802 if (IS_DEREF_OP(tree) && IS_DEREF_OP(tree->left))
2803 left = geniCodeRValue(left,TRUE);
2805 left = operandFromAst(tree->left);
2807 if (tree->opval.op == INC_OP ||
2808 tree->opval.op == DEC_OP) {
2810 right= operandFromAst(tree->right);
2813 right= operandFromAst(tree->right);
2817 /* now depending on the type of operand */
2818 /* this will be a biggy */
2819 switch (tree->opval.op) {
2821 case '[' : /* array operation */
2823 sym_link *ltype = operandType(left);
2824 left= geniCodeRValue (left,IS_PTR(ltype->next) ? TRUE : FALSE);
2825 right=geniCodeRValue (right,TRUE);
2828 return geniCodeArray (left,right);
2830 case '.' : /* structure dereference */
2831 if (IS_PTR(operandType(left)))
2832 left = geniCodeRValue(left,TRUE);
2834 left = geniCodeRValue(left,FALSE);
2836 return geniCodeStruct (left,right,tree->lvalue);
2838 case PTR_OP: /* structure pointer dereference */
2841 pType = operandType(left);
2842 left = geniCodeRValue(left,TRUE);
2844 setOClass (pType,getSpec(operandType(left)));
2847 return geniCodeStruct (left, right,tree->lvalue);
2849 case INC_OP: /* increment operator */
2851 return geniCodePostInc (left);
2853 return geniCodePreInc (right);
2855 case DEC_OP: /* decrement operator */
2857 return geniCodePostDec (left);
2859 return geniCodePreDec (right);
2861 case '&' : /* bitwise and or address of operator */
2862 if ( right ) { /* this is a bitwise operator */
2863 left= geniCodeRValue(left,FALSE);
2864 right= geniCodeRValue(right,FALSE);
2865 return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
2867 return geniCodeAddressOf (left);
2869 case '|': /* bitwise or & xor */
2871 return geniCodeBitwise (geniCodeRValue(left,FALSE),
2872 geniCodeRValue(right,FALSE),
2877 return geniCodeDivision (geniCodeRValue(left,FALSE),
2878 geniCodeRValue(right,FALSE));
2881 return geniCodeModulus (geniCodeRValue(left,FALSE),
2882 geniCodeRValue(right,FALSE));
2885 return geniCodeMultiply (geniCodeRValue(left,FALSE),
2886 geniCodeRValue(right,FALSE));
2888 return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
2892 return geniCodeSubtract (geniCodeRValue(left,FALSE),
2893 geniCodeRValue(right,FALSE));
2895 return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
2899 return geniCodeAdd (geniCodeRValue(left,FALSE),
2900 geniCodeRValue(right,FALSE));
2902 return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
2905 return geniCodeLeftShift (geniCodeRValue(left,FALSE),
2906 geniCodeRValue(right,FALSE));
2909 return geniCodeRightShift (geniCodeRValue(left,FALSE),
2910 geniCodeRValue(right,FALSE));
2912 return geniCodeCast (operandType(left),
2913 geniCodeRValue(right,FALSE),FALSE);
2919 return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2923 operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2924 setOperandType(op, UCHARTYPE);
2935 return geniCodeLogic (geniCodeRValue(left,FALSE),
2936 geniCodeRValue(right,FALSE),
2939 return geniCodeConditional (tree);
2942 return operandFromLit(getSize(tree->right->ftype));
2946 sym_link *rtype = operandType(right);
2947 sym_link *ltype = operandType(left);
2948 if (IS_PTR(rtype) && IS_ITEMP(right)
2949 && right->isaddr && checkType(rtype->next,ltype)==1)
2950 right = geniCodeRValue(right,TRUE);
2952 right = geniCodeRValue(right,FALSE);
2954 geniCodeAssign (left,right,0);
2959 geniCodeAssign(left,
2960 geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
2962 geniCodeRValue(right,FALSE)),0);
2966 geniCodeAssign(left,
2967 geniCodeDivision(geniCodeRValue(operandFromOperand(left),
2969 geniCodeRValue(right,FALSE)),0);
2972 geniCodeAssign(left,
2973 geniCodeModulus(geniCodeRValue(operandFromOperand(left),
2975 geniCodeRValue(right,FALSE)),0);
2978 sym_link *rtype = operandType(right);
2979 sym_link *ltype = operandType(left);
2980 if (IS_PTR(rtype) && IS_ITEMP(right)
2981 && right->isaddr && checkType(rtype->next,ltype)==1)
2982 right = geniCodeRValue(right,TRUE);
2984 right = geniCodeRValue(right,FALSE);
2987 return geniCodeAssign(left,
2988 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
2994 sym_link *rtype = operandType(right);
2995 sym_link *ltype = operandType(left);
2996 if (IS_PTR(rtype) && IS_ITEMP(right)
2997 && right->isaddr && checkType(rtype->next,ltype)==1) {
2998 right = geniCodeRValue(right,TRUE);
3001 right = geniCodeRValue(right,FALSE);
3004 geniCodeAssign (left,
3005 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
3011 geniCodeAssign (left,
3012 geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
3014 geniCodeRValue(right,FALSE)),0);
3017 geniCodeAssign(left,
3018 geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
3020 geniCodeRValue(right,FALSE)),0);
3023 geniCodeAssign (left,
3024 geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
3026 geniCodeRValue(right,FALSE),
3028 operandType(left)),0);
3031 geniCodeAssign (left,
3032 geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3034 geniCodeRValue(right,FALSE),
3036 operandType(left)),0);
3039 geniCodeAssign (left,
3040 geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3042 geniCodeRValue(right,FALSE),
3044 operandType(left)),0);
3046 return geniCodeRValue(right,FALSE);
3049 return geniCodeCall (ast2iCode(tree->left),
3052 geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3053 return ast2iCode (tree->right);
3056 geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3057 return ast2iCode (tree->right);
3060 geniCodeFunctionBody ( tree );
3064 geniCodeReturn (right);
3072 geniCodeSwitch (tree);
3076 geniCodeInline (tree);
3083 /*-----------------------------------------------------------------*/
3084 /* reverseICChain - gets from the list and creates a linkedlist */
3085 /*-----------------------------------------------------------------*/
3086 iCode *reverseiCChain ()
3088 iCode *loop = NULL ;
3089 iCode *prev = NULL ;
3091 while ((loop = getSet(&iCodeChain))) {
3102 /*-----------------------------------------------------------------*/
3103 /* iCodeFromAst - given an ast will convert it to iCode */
3104 /*-----------------------------------------------------------------*/
3105 iCode *iCodeFromAst ( ast *tree )
3107 returnLabel = newiTempLabel("_return");
3108 entryLabel = newiTempLabel("_entry") ;
3110 return reverseiCChain ();